[关闭]
@yudesong 2017-06-24T15:07:50.000000Z 字数 12605 阅读 607

yudesong 2017/6/24


二叉树
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. #include <stack>
  5. using namespace std;
  6. typedef struct Node
  7. {
  8. char data;
  9. struct Node *left,*right;
  10. }BTree;
  11. BTree* CreateTree(BTree *T)
  12. {
  13. char ch;
  14. scanf("%c",&ch);
  15. if(ch=='#') T=NULL;
  16. else
  17. {
  18. T=(BTree *)malloc(sizeof(BTree));
  19. T->data = ch;
  20. T->left = CreateTree(T->left);
  21. T->right = CreateTree(T->right);
  22. }
  23. return T;
  24. }
  25. void PreOrder(BTree *T)
  26. {
  27. if(T)
  28. {
  29. printf("%c",T->data);
  30. PreOrder(T->left);
  31. PreOrder(T->right);
  32. }
  33. }
  34. //先序遍历非递归算法
  35. void PreOrder1(BTree *T)
  36. {
  37. int top = -1;
  38. BTree *p;
  39. BTree *Str[100];
  40. if(T!=NULL)
  41. {
  42. top++;
  43. Str[top] = T;
  44. while(top>-1)
  45. {
  46. p = Str[top];
  47. printf("%c",p->data);
  48. top--;
  49. if(p->right!=NULL)
  50. {
  51. top++;
  52. Str[top] = p->right;
  53. }
  54. if(p->left!=NULL)
  55. {
  56. top++;
  57. Str[top] = p->left;
  58. }
  59. }
  60. }
  61. }
  62. void CengCi(BTree *T)
  63. {
  64. int font,rear;
  65. BTree *Str[10];
  66. BTree *p;
  67. font=rear=-1;
  68. if(T)
  69. {
  70. rear = (rear+1)%10;
  71. Str[rear] = T;
  72. while(font!=rear)
  73. {
  74. font = (font+1)%10;
  75. p = Str[font];
  76. printf("%c",p->data);
  77. if(p->left)
  78. {
  79. rear=(rear+1)%10;
  80. Str[rear] = p->left;
  81. }
  82. if(p->right)
  83. {
  84. rear=(rear+1)%10;
  85. Str[rear] = p->right;
  86. }
  87. }
  88. }
  89. }
  90. int sumLeaf(BTree *T)
  91. {
  92. int sum=0,l=0,r=0;
  93. if(T)
  94. {
  95. if(T->left==NULL&&T->right==NULL)
  96. sum++;
  97. l = sumLeaf(T->left);
  98. sum+=l;
  99. r = sumLeaf(T->right);
  100. sum+=r;
  101. }
  102. return sum;
  103. }
  104. int deapTree(BTree *T)
  105. {
  106. int deap,ldeap,rdeap;
  107. if(T== NULL) deap = 0;
  108. else
  109. {
  110. ldeap = deapTree(T->left);
  111. rdeap = deapTree(T->right);
  112. deap = 1+(ldeap>rdeap? ldeap:rdeap);
  113. }
  114. return deap;
  115. }
  116. BTree* invertTree(BTree *T)
  117. {
  118. if(T==NULL) return NULL;
  119. BTree *node = invertTree(T->left);
  120. T->left = invertTree(T->right);
  121. T->right = node;
  122. return T;
  123. }
  124. BTree* invertTree1(BTree *T)
  125. {
  126. if(T==NULL) return NULL;
  127. stack<BTree*> stack;
  128. stack.push(T);
  129. while(!stack.empty())
  130. {
  131. BTree *p = stack.top();
  132. stack.pop();
  133. BTree *tmp;
  134. tmp = p->left;
  135. p->left = p->right;
  136. p->right = tmp;
  137. if(p->left) stack.push(p->left);
  138. if(p->right) stack.push(p->right);
  139. }
  140. return T;
  141. }
  142. bool isEqual(BTree *T1,BTree *T2)
  143. {
  144. if(T1==NULL && T2==NULL) return 1;
  145. if(T1==NULL || T2==NULL) return 0;
  146. if(T1->data==T2->data)
  147. {
  148. return isEqual(T1->left,T2->left)&&isEqual(T1->right,T2->right);
  149. }
  150. else
  151. return 0;
  152. }
  153. int main()
  154. {
  155. BTree *T;
  156. T = CreateTree(T);
  157. // T = invertTree(T);
  158. // ABC##DE#G##F###
  159. // 421##3##76##9##
  160. // PreOrder(T);
  161. // PreOrder1(T);
  162. CengCi(invertTree1(T));
  163. printf("\n%d",sumLeaf(T));
  164. printf("\n%d",deapTree(T));
  165. return 0;
  166. }

构造哈夫曼树

  1. /*
  2. 根据Huffman树的构造原理进行构造 ...
  3. 哈夫曼树在编码压缩的领域有很好的应用,利用Huffman进行编码可以保证
  4. 数据传输的无二义性 。
  5. 但是要注意的是 对于出现频率大的数据我们应该尽量放在离根节点近的
  6. 地方进行编码 ,出现频率小的数据我们可以放在距离根节点小的地方。
  7. 这样可以提高数据的传输效率 。
  8. */
  9. #include "stdio.h"
  10. #include "malloc.h"
  11. ///节点声明
  12. typedef struct node{
  13. node *lChild ;
  14. node *rChild ;
  15. int data ;//权值
  16. }TreeNode ;
  17. //数组a表示权的数组 n是个数
  18. TreeNode * CreateHuffmanTree(int a[],int n) ;
  19. //查找出2个权值最小的节点的下标
  20. void FindLittle(int *x1,int *x2 ,TreeNode**pArr,int n) ;
  21. //数组a表示权的数组 n是个数
  22. TreeNode * CreateHuffmanTree(int a[],int n)
  23. {
  24. //动态产生指针数组
  25. TreeNode**pArr=(TreeNode**)malloc(sizeof(TreeNode*)*n);
  26. TreeNode*p =NULL;//用于返回哈夫曼树的根节点的指针
  27. int k1,k2 ;
  28. //k1代表最小权 k2代表次小权
  29. //用于做为 FindLittle的参数查找最小权下标
  30. for(int i=0;i<n;i++)
  31. {
  32. pArr[i]=new TreeNode ;
  33. //为节点指针数组动态分配指向的对象
  34. pArr[i]->data=a[i] ;
  35. pArr[i]->lChild=pArr[i]->rChild=NULL ;
  36. //初始化每个节点的左右节点都是空
  37. }
  38. //因为哈夫曼树是循环的从节点数组中找出权值最小的两个节点进行组合
  39. //并从数组中删除这两个节点,并把合并后的节点添加到数组中。
  40. for(i=0;i<n-1;i++) //因为最后还剩下一个节点所以就会挑选n-1次
  41. {
  42. FindLittle(&k1,&k2,pArr,n) ; //查找2个最小权节点下标
  43. p=new TreeNode;
  44. //循环组合最后的p指向的节点便是最终的pRoot
  45. p->data=pArr[k1]->data+pArr[k2]->data ;
  46. p->lChild=pArr[k1] ;
  47. p->rChild=pArr[k2] ;
  48. //将合并后的新节点赋值给pArr最小的那个下标
  49. pArr[k1]=p ;
  50. pArr[k2]=NULL ;
  51. // 次下标设置NULL, k1和k2也可以反过来这个具体我们自己定
  52. }
  53. free(pArr) ;//释放指针数组
  54. return p;
  55. }
  56. //查找出2个权值最小的节点的下标
  57. void FindLittle(int *x1,int *x2 ,TreeNode**pArr,int n)
  58. {
  59. int k1,k2; //保存权最小的两个节点下标
  60. k1=-1 ; //表示没有找到数据
  61. //找出其中的前两个元素不为NULL的下标
  62. for(int i=0;i<n;i++)
  63. {
  64. if(pArr[i]!=NULL&&k1==-1)
  65. {
  66. k1=i ; //第一个下标
  67. continue ;
  68. }
  69. if(pArr[i]!=NULL)
  70. {
  71. k2=i ;
  72. break;//找到第二个下标退出循环
  73. }
  74. }
  75. ////// 最小权的2个下标的搜索实现//////////
  76. //我们是先获取k1 后获取k2所以一开始 一定是从k2开始循环的
  77. for(i=k2;i<n;i++)
  78. {
  79. if(pArr[i]!=NULL)
  80. {
  81. //如果下标k1的权 小于当前下标的元素的权
  82. if(pArr[i]->data<pArr[k1]->data )
  83. {
  84. k2=k1; //此时还是k1<k2满足我们返回的结果
  85. k1=i ;
  86. }
  87. else if(pArr[i]->data<pArr[k2]->data)
  88. {
  89. k2=i ;
  90. }
  91. }
  92. }
  93. *x1=k1 ;
  94. *x2=k2 ;
  95. }
  96. ///哈夫曼树的先序遍历
  97. void PreHufOrder(TreeNode*p) //先序遍历
  98. {
  99. if(p!=NULL)
  100. {
  101. printf("%d ",p->data) ;
  102. PreHufOrder(p->lChild) ;
  103. PreHufOrder(p->rChild) ;
  104. }
  105. }
  106. //中序遍历
  107. void InHufOrder(TreeNode*p)
  108. {
  109. if(p!=NULL)
  110. {
  111. InHufOrder(p->lChild) ;
  112. printf("%d ",p->data) ;
  113. InHufOrder(p->rChild) ;
  114. }
  115. }
  116. //后续遍历
  117. void PostHufOrder(TreeNode*p)
  118. {
  119. if(p!=NULL)
  120. {
  121. InHufOrder(p->lChild) ;
  122. InHufOrder(p->rChild) ;
  123. printf("%d ",p->data) ;
  124. }
  125. }
  126. //清空树
  127. void ClearHufTree(TreeNode*p)
  128. {
  129. if(p!=NULL)
  130. {
  131. ClearHufTree(p->lChild) ;
  132. ClearHufTree(p->rChild) ;
  133. delete p ;
  134. }
  135. }
  136. int main()
  137. {
  138. int a[]={3,5,3,8,7,9,4,2,4,5,6,3,2,3} ; //权值
  139. //创建huffman树
  140. TreeNode*p=::CreateHuffmanTree(a,sizeof(a)/sizeof(int)) ;
  141. printf("Huffman前序遍历:\n") ;
  142. PreHufOrder(p) ; //前序遍历huffmanTree
  143. printf("\n");
  144. printf("Huffman后序遍历:\n") ;
  145. PostHufOrder(p) ;//后序遍历
  146. printf("\n");
  147. printf("Huffman中序遍历:\n") ;
  148. InHufOrder(p) ;//中序遍历
  149. printf("\n");
  150. ClearHufTree(p) ;//清空树
  151. return 0 ;
  152. }
1. 求二叉树中的节点个数

递归解法: (1)如果二叉树为空,节点个数为0 (2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1

参考代码如下:

  1. int GetNodeNum(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL) // 递归出口
  4. return 0;
  5. return GetNodeNum(pRoot->m_pLeft)+GetNodeNum(pRoot->m_pRight)+1;
  6. }
2. 求二叉树的深度

递归解法: (1)如果二叉树为空,二叉树的深度为0 (2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1

参考代码如下:

  1. int GetDepth(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL) // 递归出口
  4. return 0;
  5. int depthLeft = GetDepth(pRoot->m_pLeft);
  6. int depthRight = GetDepth(pRoot->m_pRight);
  7. return depthLeft>depthRight?(depthLeft+1):(depthRight+1);
  8. }
3. 前序遍历,中序遍历,后序遍历 前序遍历

递归解法: (1)如果二叉树为空,空操作 (2)如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树

参考代码如下:

  1. void PreOrderTraverse(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL)
  4. return;
  5. Visit(pRoot); // 访问根节点
  6. PreOrderTraverse(pRoot->m_pLeft); // 前序遍历左子树
  7. PreOrderTraverse(pRoot->m_pRight); // 前序遍历右子树
  8. }

中序遍历递归解法 (1)如果二叉树为空,空操作。 (2)如果二叉树不为空,中序遍历左子树,访问根节点,中序遍历右子树

参考代码如下:

  1. void InOrderTraverse(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL)
  4. return;
  5. InOrderTraverse(pRoot->m_pLeft); // 中序遍历左子树
  6. Visit(pRoot); // 访问根节点
  7. InOrderTraverse(pRoot->m_pRight); // 中序遍历右子树
  8. }

后序遍历递归解法 (1)如果二叉树为空,空操作 (2)如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点

参考代码如下:

  1. void PostOrderTraverse(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL)
  4. return;
  5. PostOrderTraverse(pRoot->m_pLeft); // 后序遍历左子树
  6. PostOrderTraverse(pRoot->m_pRight); // 后序遍历右子树
  7. Visit(pRoot); // 访问根节点
  8. }
4.分层遍历二叉树

(按层次从上往下,从左往右) 相当于广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点,访问,若左子节点或右子节点不为空,将其压入队列。

  1. void LevelTraverse(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL)
  4. return;
  5. queue<BinaryTreeNode *> q;
  6. q.push(pRoot);
  7. while(!q.empty())
  8. {
  9. BinaryTreeNode * pNode = q.front();
  10. q.pop();
  11. Visit(pNode); // 访问节点
  12. if(pNode->m_pLeft != NULL)
  13. q.push(pNode->m_pLeft);
  14. if(pNode->m_pRight != NULL)
  15. q.push(pNode->m_pRight);
  16. }
  17. return;
  18. }
5. 将二叉查找树变为有序的双向链表 要求不能创建新节点,只调整指针

递归解法: (1)如果二叉树查找树为空,不需要转换,对应双向链表的第一个节点是NULL,最后一个节点是NULL (2)如果二叉查找树不为空: 如果左子树为空,对应双向有序链表的第一个节点是根节点,左边不需要其他操作; 如果左子树不为空,转换左子树,二叉查找树对应双向有序链表的第一个节点就是左子树转换后双向有序链表的第一个节点,同时将根节点和左子树转换后的双向有序链 表的最后一个节点连接; 如果右子树为空,对应双向有序链表的最后一个节点是根节点,右边不需要其他操作; 如果右子树不为空,对应双向有序链表的最后一个节点就是右子树转换后双向有序链表的最后一个节点,同时将根节点和右子树转换后的双向有序链表的第一个节点连 接。 参考代码如下:

  1. /************************************************************
  2. 参数:
  3. pRoot: 二叉查找树根节点指针
  4. pFirstNode: 转换后双向有序链表的第一个节点指针
  5. pLastNode: 转换后双向有序链表的最后一个节点指针
  6. ************************************************************/
  7. void Convert(BinaryTreeNode * pRoot,
  8. BinaryTreeNode *&pFirstNode,BinaryTreeNode *&pLastNode)
  9. {
  10. BinaryTreeNode *pFirstLeft,*pLastLeft,*pFirstRight,*pLastRight;
  11. if(pRoot == NULL)
  12. {
  13. pFirstNode = NULL;
  14. pLastNode = NULL;
  15. return;
  16. }
  17. if(pRoot->m_pLeft == NULL)
  18. {
  19. //如果左子树为空,对应双向有序链表的第一个节点是根节点
  20. pFirstNode = pRoot;
  21. }else
  22. {
  23. Convert(pRoot->m_pLeft, pFirstLeft, pLastLeft);
  24. //二叉查找树对应双向有序链表的第一个节点就是左子树转换
  25. //后双向有序链表的第一个节点
  26. pFirstNode = pFirstLeft;
  27. // 将根节点和左子树转换后的双向有序链表的最后一个节点连接
  28. pRoot->m_pLeft = pLastLeft;
  29. pLastLeft->m_pRight = pRoot;
  30. }
  31. if(pRoot->m_pRight == NULL)
  32. {
  33. //对应双向有序链表的最后一个节点是根节点
  34. pLastNode = pRoot;
  35. }else
  36. {
  37. Convert(pRoot->m_pRight, pFirstRight, pLastRight);
  38. //对应双向有序链表的最后一个节点就是右子树转换后双向有序链表的最后一个节点
  39. pLastNode = pLastRight;
  40. // 将根节点和右子树转换后的双向有序链表的第一个节点连接
  41. pRoot->m_pRight = pFirstRight;
  42. pFirstRight->m_pLeft = pRoot;
  43. }
  44. return;
  45. }
6. 求二叉树第K层的节点个数

递归解法: (1)如果二叉树为空或者k<1返回0 (2)如果二叉树不为空并且k==1,返回1 (3)如果二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和

参考代码如下:

  1. int GetNodeNumKthLevel(BinaryTreeNode * pRoot, int k)
  2. {
  3. if(pRoot == NULL || k < 1)
  4. return 0;
  5. if(k == 1)
  6. return 1;
  7. // 左子树中k-1层的节点个数
  8. int numLeft = GetNodeNumKthLevel(pRoot->m_pLeft, k-1);
  9. // 右子树中k-1层的节点个数
  10. int numRight = GetNodeNumKthLevel(pRoot->m_pRight, k-1);
  11. return (numLeft + numRight);
  12. }
7. 求二叉树中叶子节点的个数

递归解法: (1)如果二叉树为空,返回0 (2)如果二叉树不为空且左右子树为空,返回1 (3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数

参考代码如下:

  1. int GetLeafNodeNum(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL)
  4. return 0;
  5. if(pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL)
  6. return 1;
  7. // 左子树中叶节点的个数
  8. int numLeft = GetLeafNodeNum(pRoot->m_pLeft);
  9. // 右子树中叶节点的个数
  10. int numRight = GetLeafNodeNum(pRoot->m_pRight);
  11. return (numLeft + numRight);
  12. }
8. 判断两棵二叉树是否结构相同 不考虑数据内容。结构相同意味着对应的左子树和对应的右子树都结构相同。

递归解法: (1)如果两棵二叉树都为空,返回真 (2)如果两棵二叉树一棵为空,另一棵不为空,返回假 (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假

参考代码如下:

  1. bool StructureCmp(BinaryTreeNode *pRoot1,BinaryTreeNode *pRoot2)
  2. {
  3. // 都为空,返回真
  4. if(pRoot1 == NULL && pRoot2 == NULL) return true;
  5. // 有一个为空,一个不为空,返回假
  6. else if(pRoot1 == NULL || pRoot2 == NULL) return false;
  7. // 比较对应左子树
  8. bool resultLeft = StructureCmp(pRoot1->m_pLeft, pRoot2->m_pLeft);
  9. // 比较对应右子树
  10. bool resultRight=StructureCmp(pRoot1->m_pRight,pRoot2->m_pRight);
  11. return (resultLeft && resultRight);
  12. }
9. 判断二叉树是不是平衡二叉树

递归解法: (1)如果二叉树为空,返回真 (2)如果二叉树不为空,如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假

参考代码:

  1. bool IsAVL(BinaryTreeNode * pRoot, int & height)
  2. {
  3. if(pRoot == NULL) // 空树,返回真
  4. {
  5. height = 0;
  6. return true;
  7. }
  8. int heightLeft;
  9. bool resultLeft = IsAVL(pRoot->m_pLeft, heightLeft);
  10. int heightRight;
  11. bool resultRight = IsAVL(pRoot->m_pRight, heightRight);
  12. // 左子树和右子树都是AVL,并且高度相差不大于1,返回真
  13. if(resultLeft&&resultRight&&abs(heightLeft-heightRight)<=1)
  14. {
  15. height = max(heightLeft, heightRight) + 1;
  16. return true;
  17. }
  18. else
  19. {
  20. height = max(heightLeft, heightRight) + 1;
  21. return false;
  22. }
  23. }
10. 求二叉树的镜像

递归解法: (1)如果二叉树为空,返回空 (2)如果二叉树不为空,求左子树和右子树的镜像,然后交换左子树和右子树

参考代码如下:

  1. BinaryTreeNode * Mirror(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL) // 返回NULL
  4. return NULL;
  5. BinaryTreeNode * pLeft = Mirror(pRoot->m_pLeft);
  6. BinaryTreeNode * pRight = Mirror(pRoot->m_pRight);
  7. // 交换左子树和右子树
  8. pRoot->m_pLeft = pRight;
  9. pRoot->m_pRight = pLeft;
  10. return pRoot;
  11. }
11. 求二叉树中两个节点的最低公共祖先节点

递归解法: (1)如果两个节点分别在根节点的左子树和右子树,则返回根节点 (2)如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树

参考代码如下:

  1. bool FindNode(BinaryTreeNode * pRoot, BinaryTreeNode * pNode)
  2. {
  3. if(pRoot == NULL || pNode == NULL) return false;
  4. if(pRoot == pNode) return true;
  5. bool found = FindNode(pRoot->m_pLeft, pNode);
  6. if(!found) found = FindNode(pRoot->m_pRight, pNode);
  7. return found;
  8. }
  9. BinaryTreeNode *GetLastCommonParent(BinaryTreeNode *pRoot,
  10. BinaryTreeNode * pNode1,BinaryTreeNode * pNode2)
  11. {
  12. if(FindNode(pRoot->m_pLeft, pNode1))
  13. {
  14. if(FindNode(pRoot->m_pRight, pNode2))
  15. return pRoot;
  16. else
  17. return GetLastCommonParent(pRoot->m_pLeft, pNode1, pNode2);
  18. }else{
  19. if(FindNode(pRoot->m_pLeft, pNode2)) return pRoot;
  20. else
  21. return GetLastCommonParent(pRoot->m_pRight,pNode1,pNode2);
  22. }
  23. }
12. 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离

递归解法: (1)如果二叉树为空,返回0,同时记录左子树和右子树的深度,都为0 (2)如果二叉树不为空,最大距离要么是左子树中的最大距离,要么是右子树中的最大距离,要么是左子树节点中到根节点的最大距离+右子树节点中到根节点的最大距离,同时记录左子树和右子树节点中到根节点的最大距离。

参考代码如下:

  1. int GetMaxDistance(BinaryTreeNode*pRoot,int&maxLeft,int &maxRight)
  2. {
  3. // maxLeft, 左子树中的节点距离根节点的最远距离
  4. // maxRight, 右子树中的节点距离根节点的最远距离
  5. if(pRoot == NULL)
  6. {
  7. maxLeft = 0;
  8. maxRight = 0;
  9. return 0;
  10. }
  11. int maxLL, maxLR, maxRL, maxRR;
  12. int maxDistLeft, maxDistRight;
  13. if(pRoot->m_pLeft != NULL)
  14. {
  15. maxDistLeft=GetMaxDistance(pRoot->m_pLeft,maxLL, maxLR);
  16. maxLeft = max(maxLL, maxLR) + 1;
  17. }
  18. else
  19. {
  20. maxDistLeft = 0;
  21. maxLeft = 0;
  22. }
  23. if(pRoot->m_pRight != NULL)
  24. {
  25. maxDistRight = GetMaxDistance(pRoot->m_pRight, maxRL, maxRR);
  26. maxRight = max(maxRL, maxRR) + 1;
  27. }
  28. else
  29. {
  30. maxDistRight = 0;
  31. maxRight = 0;
  32. }
  33. return max(max(maxDistLeft, maxDistRight), maxLeft+maxRight);
  34. }
13. 由前序遍历序列和中序遍历序列重建二叉树

二叉树前序遍历序列中,第一个元素总是树的根节点的值。中序遍历序列中,左子树的节点的值位于根节点的值的左边,右子树的节点的值位 于根节点的值的右边。 递归解法: (1)如果前序遍历为空或中序遍历为空或节点个数小于等于0,返回NULL。 (2)创建根节点。前序遍历的第一个数据就是根节点的数据,在中序遍历中找到根节点的位置,可分别得知左子树和右子树的前序和中序遍 历序列,重建左右子树。

  1. BinaryTreeNode * RebuildBinaryTree(int* pPreOrder, int* pInOrder, int nodeNum)
  2. {
  3. if(pPreOrder == NULL || pInOrder == NULL || nodeNum <= 0)
  4. return NULL;
  5. BinaryTreeNode * pRoot = new BinaryTreeNode;
  6. // 前序遍历的第一个数据就是根节点数据
  7. pRoot->m_nValue = pPreOrder[0];
  8. pRoot->m_pLeft = NULL;
  9. pRoot->m_pRight = NULL;
  10. // 查找根节点在中序遍历中的位置,中序遍历中,根节点左边为左子树,右边为右子树
  11. int rootPositionInOrder = -1;
  12. for(int i = 0; i < nodeNum; i++)
  13. if(pInOrder[i] == pRoot->m_nValue)
  14. {
  15. rootPositionInOrder = i;
  16. break;
  17. }
  18. if(rootPositionInOrder == -1)
  19. {
  20. throw std::exception("Invalid input.");
  21. }
  22. // 重建左子树
  23. int nodeNumLeft = rootPositionInOrder;
  24. int * pPreOrderLeft = pPreOrder + 1;
  25. int * pInOrderLeft = pInOrder;
  26. pRoot->m_pLeft = RebuildBinaryTree(pPreOrderLeft, pInOrderLeft, nodeNumLeft);
  27. // 重建右子树
  28. int nodeNumRight = nodeNum - nodeNumLeft - 1;
  29. int * pPreOrderRight = pPreOrder + 1 + nodeNumLeft;
  30. int * pInOrderRight = pInOrder + nodeNumLeft + 1;
  31. pRoot->m_pRight = RebuildBinaryTree(pPreOrderRight, pInOrderRight, nodeNumRight);
  32. return pRoot;
  33. }
14.判断二叉树是不是完全二叉树

若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全 二叉树。 有如下算法,按层次(从上到下,从左到右)遍历二叉树,当遇到一个节点的左子树为空时,则该节点右子树必须为空,且后面遍历的节点左 右子树都必须为空,否则不是完全二叉树。

  1. bool IsCompleteBinaryTree(BinaryTreeNode * pRoot)
  2. {
  3. if(pRoot == NULL)
  4. return false;
  5. queue<BinaryTreeNode *> q;
  6. q.push(pRoot);
  7. bool mustHaveNoChild = false;
  8. bool result = true;
  9. while(!q.empty())
  10. {
  11. BinaryTreeNode * pNode = q.front();
  12. q.pop();
  13. if(mustHaveNoChild) // 已经出现了有空子树的节点了,后面出现的必须为叶节点(左右子树都为空)
  14. {
  15. if(pNode->m_pLeft != NULL || pNode->m_pRight != NULL)
  16. {
  17. result = false;
  18. break;
  19. }
  20. }
  21. else
  22. {
  23. if(pNode->m_pLeft != NULL && pNode->m_pRight != NULL)
  24. {
  25. q.push(pNode->m_pLeft);
  26. q.push(pNode->m_pRight);
  27. }
  28. else if(pNode->m_pLeft != NULL && pNode->m_pRight == NULL)
  29. {
  30. mustHaveNoChild = true;
  31. q.push(pNode->m_pLeft);
  32. }
  33. else if(pNode->m_pLeft == NULL && pNode->m_pRight != NULL)
  34. {
  35. result = false;
  36. break;
  37. }
  38. else
  39. {
  40. mustHaveNoChild = true;
  41. }
  42. }
  43. }
  44. return result;
  45. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注