[关闭]
@songpfei 2016-05-20T03:15:50.000000Z 字数 6658 阅读 2093

二叉树

数据结构


1.概述

定义:树是一个或多个节点的有效集合,且其中:

2 二叉树

2.1基本概念

  1. 定义:二叉树(binary tree)是有限多个节点的集合,这个集合或者空集,或者 由一个根节点和两颗互不相交的、分别称为左子树和右子树组成。
  2. 二叉树的性质

    • 在二叉树中,第i层的节点数最多为
    • 在深度为k的二叉树中,节点总数最多为
      叶子节点的个数与度为2的节点n_2个数之间的关系为:
  3. 满二叉树(full binary tree):是深度为k的满二叉树是具有个节点的二叉树,除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树

  4. 完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。

2. 2二叉树的存储表示

  1. 数组存储表示:对节点从1到n进行编号,因此可以使用一个一维数组来存储这些点。
    引理:对于一课n个节点的完全二叉树(深度)采用顺序存储 表示,那么对于任意一个下标为i节点有:
    • ,则其父节点parent(i)的编号为i/2;若i=1,则i是根节点;
    • ,则其左孩子为2i;
    • ,则其右孩子为2i+1;
  2. 链式存储:
    树的头结点定义:
  1. typedef int ElementType;
  2. typedef struct BinaryTreeNode BinTree;
  3. struct BinaryTreeNode
  4. {
  5. ElementType data;
  6. BinaryTreeNode* left;
  7. BinaryTreeNode* right;
  8. };

2.3 二叉树的遍历

三种遍历:
- LVR:中序遍历(inoder);
- LRV:后续遍历(postorder);
- VLR:前序遍历(preoeder);

表达式树:表达式树的树叶是操作数,常数或变量,二其他的节点为操作符(operator),表达式三种遍历顺序与表达式的中缀(infix)、后缀(postfix)和前缀(prefix)形式之间存在一种自然的对应关系。
代码实现:

  1. #ifndef BINARYTREE_H
  2. #define BINARYTREE_H
  3. typedef int ElementType;
  4. struct BinaryTreeNode
  5. {
  6. ElementType data;
  7. BinaryTreeNode* left;
  8. BinaryTreeNode* right;
  9. };
  10. void PreOrder(BinaryTreeNode* pRoot);//前序遍历
  11. void PostOrder(BinaryTreeNode* pRoot);//后续遍历
  12. void InOrder(BinaryTreeNode* pRoot);//中序遍历
  13. void LevelOrder(BinaryTreeNode* pRoot);//层序遍历
  14. #endif
  1. #include"BinaryTree.h"
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<queue>
  5. /*1.递归的实现二叉树的遍历*/
  6. //前序遍历
  7. void PreOrder(BinaryTreeNode* pRoot)
  8. {
  9. if (pRoot == NULL)
  10. return;
  11. printf("%d ", pRoot->data);
  12. PreOrder(pRoot->left);
  13. PreOrder(pRoot->right);
  14. }
  15. //后续遍历
  16. void PostOrder(BinaryTreeNode* pRoot)
  17. {
  18. if (pRoot == NULL)
  19. return;
  20. PreOrder(pRoot->left);
  21. PreOrder(pRoot->right);
  22. printf("%d ", pRoot->data);
  23. }
  24. //中序遍历
  25. void InOrder(BinaryTreeNode* pRoot)
  26. {
  27. if (pRoot == NULL)
  28. return;
  29. PreOrder(pRoot->left);
  30. printf("%d ", pRoot->data);
  31. PreOrder(pRoot->right);
  32. }
  33. //层序遍历
  34. void LevelOrder(BinaryTreeNode* pRoot)
  35. {
  36. if (pRoot == NULL)
  37. return;
  38. std::queue<BinaryTreeNode*> tree_node_queue;
  39. tree_node_queue.push(pRoot);
  40. while (tree_node_queue.size()>0)
  41. {
  42. pRoot = tree_node_queue.front();
  43. tree_node_queue.pop();
  44. printf("%d ", pRoot->data);
  45. if (pRoot->left != NULL)
  46. tree_node_queue.push(pRoot->left);
  47. if (pRoot->right != NULL)
  48. tree_node_queue.push(pRoot->right);
  49. }
  50. }

3. 二叉搜索树

3.1 概述

3.2 二叉搜索树的各种操作

  1. #ifndef BINARYTREE_H
  2. #define BINARYTREE_H
  3. typedef int ElementType;
  4. struct BinaryTreeNode
  5. {
  6. ElementType data;
  7. BinaryTreeNode* left;
  8. BinaryTreeNode* right;
  9. };
  10. void PreOrder(BinaryTreeNode* pRoot);//前序遍历
  11. void PostOrder(BinaryTreeNode* pRoot);//后续遍历
  12. void InOrder(BinaryTreeNode* pRoot);//中序遍历
  13. void LevelOrder(BinaryTreeNode* pRoot);//层序遍历
  14. BinaryTreeNode* BinaryTreeSearchRecursive(BinaryTreeNode* pRoot, ElementType key);//二叉搜索树查找(递归)
  15. BinaryTreeNode* BinaryTreeSearch(BinaryTreeNode* pRoot, ElementType key);//二叉搜索树查找(迭代)
  16. bool BinaryTreeInsert(BinaryTreeNode* &pRoot, ElementType key);//二叉树节点插入
  17. bool BinaryTreeDelete(BinaryTreeNode* &pRoot, ElementType key);//二叉树节点删除
  18. #endif
  1. #include"BinaryTree.h"
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<queue>
  5. /*1.递归的实现二叉树的遍历*/
  6. //前序遍历
  7. void PreOrder(BinaryTreeNode* pRoot)
  8. {
  9. if (pRoot == NULL)
  10. return;
  11. printf("%d ", pRoot->data);
  12. PreOrder(pRoot->left);
  13. PreOrder(pRoot->right);
  14. }
  15. //后续遍历
  16. void PostOrder(BinaryTreeNode* pRoot)
  17. {
  18. if (pRoot == NULL)
  19. return;
  20. PreOrder(pRoot->left);
  21. PreOrder(pRoot->right);
  22. printf("%d ", pRoot->data);
  23. }
  24. //中序遍历
  25. void InOrder(BinaryTreeNode* pRoot)
  26. {
  27. if (pRoot == NULL)
  28. return;
  29. PreOrder(pRoot->left);
  30. printf("%d ", pRoot->data);
  31. PreOrder(pRoot->right);
  32. }
  33. //层序遍历
  34. void LevelOrder(BinaryTreeNode* pRoot)
  35. {
  36. if (pRoot == NULL)
  37. return;
  38. std::queue<BinaryTreeNode*> tree_node_queue;
  39. tree_node_queue.push(pRoot);
  40. while (tree_node_queue.size() > 0)
  41. {
  42. pRoot = tree_node_queue.front();
  43. tree_node_queue.pop();
  44. printf("%d ", pRoot->data);
  45. if (pRoot->left != NULL)
  46. tree_node_queue.push(pRoot->left);
  47. if (pRoot->right != NULL)
  48. tree_node_queue.push(pRoot->right);
  49. }
  50. }
  51. //二叉搜索树查找(递归)
  52. BinaryTreeNode* BinaryTreeSearchRecursive(BinaryTreeNode* pRoot, ElementType key)
  53. {
  54. if (pRoot == NULL || key == pRoot->data)
  55. return pRoot;
  56. if (key < pRoot->data)
  57. return BinaryTreeSearchRecursive(pRoot->left, key);
  58. else
  59. return BinaryTreeSearchRecursive(pRoot->right, key);
  60. }
  61. //二叉搜索树查找(迭代)时间复杂度:o(h)
  62. BinaryTreeNode* BinaryTreeSearch(BinaryTreeNode* pRoot, ElementType key)
  63. {
  64. while (pRoot != NULL && key != pRoot->data)
  65. {
  66. if (key < pRoot->data)
  67. pRoot = pRoot->left;
  68. else
  69. pRoot = pRoot->right;
  70. }
  71. return pRoot;
  72. }
  73. //二叉树插入
  74. bool BinaryTreeInsert(BinaryTreeNode* &pRoot, ElementType key)
  75. {
  76. BinaryTreeNode* pParent = NULL;
  77. BinaryTreeNode* pNode = pRoot;
  78. while (pNode != NULL&&pNode->data != key)
  79. {
  80. pParent = pNode;
  81. if (key < pNode->data)
  82. pNode = pNode->left;
  83. else
  84. pNode = pNode->right;
  85. }
  86. if (pNode != NULL)//key已经存在
  87. return false;
  88. BinaryTreeNode* pNodeInsert = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
  89. if (pNodeInsert == NULL)//内存申请失败
  90. return false;
  91. pNodeInsert->data = key;
  92. pNodeInsert->left = pNodeInsert->right = NULL;
  93. if (pParent == NULL)//树为空,新插入的节点为根节点
  94. pRoot = pNodeInsert;
  95. else if (key < pParent->data)
  96. pParent->left = pNodeInsert;
  97. else
  98. pParent->right = pNodeInsert;
  99. return true;
  100. }
  101. //二叉树节点删除
  102. bool BinaryTreeDelete(BinaryTreeNode* &pRoot, ElementType key)
  103. {
  104. BinaryTreeNode *pNext, *pFather = NULL;
  105. BinaryTreeNode* pNode = pRoot;
  106. int pos = 0;//待删除节点的位置,0代表根节点,-1代表左节点,1代表右节点
  107. while (pNode != NULL&&pNode->data != key)
  108. {
  109. pFather = pNode;
  110. if (key < pNode->data)
  111. {
  112. pos = -1;
  113. pNode = pNode->left;
  114. }
  115. else
  116. {
  117. pos = 1;
  118. pNode = pNode->right;
  119. }
  120. }
  121. if (pNode == NULL)//节点不存在
  122. return false;
  123. if (pNode->left != NULL&&pNode->right != NULL)//待删除的节点有两个孩子
  124. {
  125. pFather = pNode;
  126. pos = -1;
  127. pNext = pNode->left;//用其左树中的最大元素替代删除元素
  128. while (pNext->right != NULL)
  129. {
  130. pos = 1;
  131. pFather = pNext;
  132. pNext = pNext->right;
  133. }
  134. pNode->data = pNext->data;//替换
  135. pNode = pNext;//更新需要删除的元素
  136. }
  137. if (pNode->left != NULL)//待删除节点只有左孩子
  138. pNext = pNode->left;
  139. else if (pNode->right != NULL)//只有右节点
  140. pNext = pNode->right;
  141. else //待删除节点没有孩子
  142. pNext = NULL;
  143. if (pos == 0)//待删除节点为根节点
  144. pRoot = pNext;
  145. else if (pos == -1)//待删除节点为左孩子
  146. pFather->left = pNext;
  147. else //待删除节点为右孩子
  148. pFather->right = pNext;
  149. delete pNode;//删除节点
  150. pNode = NULL;
  151. return true;
  152. }
  1. #include"BinaryTree.h"
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4. int main()
  5. {
  6. BinaryTreeNode* pRootNode = NULL;
  7. BinaryTreeNode* pFind;
  8. BinaryTreeInsert(pRootNode, 30);
  9. BinaryTreeInsert(pRootNode, 5);
  10. BinaryTreeInsert(pRootNode, 2);
  11. BinaryTreeInsert(pRootNode, 40);
  12. BinaryTreeInsert(pRootNode, 35);
  13. BinaryTreeInsert(pRootNode, 80);
  14. BinaryTreeInsert(pRootNode, 32);
  15. BinaryTreeInsert(pRootNode, 38);
  16. PreOrder(pRootNode);
  17. printf("1.前序遍历\n");
  18. InOrder(pRootNode);
  19. printf("2.中序遍历\n");
  20. PostOrder(pRootNode);
  21. printf("3.后序遍历\n");
  22. LevelOrder(pRootNode);
  23. printf("4.层序遍历\n");
  24. pFind = BinaryTreeSearch(pRootNode, 35);
  25. if (pFind)
  26. printf("5.找到的节点为:%d\n", pFind->data);
  27. else
  28. printf("5.未找到节点");
  29. pFind = BinaryTreeSearchRecursive(pRootNode, 33);
  30. if (pFind)
  31. printf("6.找到的节点为:%d\n", pFind->data);
  32. else
  33. printf("6.未找到节点\n");
  34. if (BinaryTreeInsert(pRootNode, 33))
  35. {
  36. printf("7.插入成功\n");
  37. LevelOrder(pRootNode);
  38. }
  39. if (BinaryTreeDelete(pRootNode, 33))
  40. {
  41. printf("8.删除成功\n");
  42. LevelOrder(pRootNode);
  43. }
  44. if (BinaryTreeDelete(pRootNode, 35))
  45. {
  46. printf("8.删除成功\n");
  47. LevelOrder(pRootNode);
  48. }
  49. return 0;
  50. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注