当前位置:   article > 正文

【数据结构·考研】树的孩子兄弟表示法_左孩子右兄弟什么意思

左孩子右兄弟什么意思

树的孩子兄弟表示法

也叫树的二叉树表示法。

树的左指针指向自己的第一个孩子,右指针指向与自己相邻的兄弟。

结构的最大优点是:它和二叉树的二叉链表表示完全一样。可利用二叉树的算法来实现对树的操作 。

左孩子右兄弟表示的树的高度 

因为二叉树表示法的根节点没有右孩子,所以树高就是左子树树高 + 1。

然后我们看下根节点第一个孩子的高度,由于第一个孩子的右子树和第一个孩子的高度是相同的,所以比较左子树 + 1的高度来和右子树来比较,如果 左子树 + 1 > 右子树,高度取左子树 + 1,否则取右子树。

  1. //左孩子右兄弟表示的树的高度
  2. int Height(Tree& t){
  3. if(t == NULL) return 0;
  4. return Height(t->left) + 1 > Height(t->right) ? Height(t->left) + 1 : Height(t->right);
  5. }

左孩子右兄弟表示的树的叶子结点数

与求二叉树叶子结点的算法相似,仅需要把判断条件修改。

  1. //左孩子右兄弟表示的树的叶子结点数
  2. int Count(Tree& t){
  3. if(t == NULL) return 0;
  4. if(t->left == NULL) return 1;
  5. return Count(t->left) + Count(t->right);
  6. }

树的总结点数

与求二叉树叶子结点的算法完全相同。

  1. //总的结点数
  2. int CountSum(Tree& t){
  3. if(t == NULL) return 0;
  4. return CountSum(t->left) + CountSum(t->right) + 1;
  5. }

树的先根遍历 

树的先根遍历,孩子是根,兄弟不是,多么精辟的话。先一边输出一边递归找孩子,等递归返回时再输出兄弟。

树的先根遍历的结果和二叉树的前序遍历的结果完全相同。

  1. //树的先根遍历
  2. void preOrder(Tree& t){
  3. if(t == NULL) return;
  4. cout<<t->val<<" ";
  5. TreeNode* p = t->left;
  6. while(p != NULL){
  7. preOrder(p); //递归找“根”
  8. p = p->right;
  9. }
  10. }

树的后根遍历

在递归的边界处输出,先一直往下找“根”,找到最后走到孩子到了边界了,打印孩子之后再开始挖我的兄弟。

树的后根遍历的结果和二叉树的中序遍历的结果完全相同。

  1. //树的后根遍历
  2. void PostOrder(Tree& t){
  3. if(t == NULL) return;
  4. TreeNode* p = t->left;
  5. while(p != NULL){
  6. PostOrder(p); //递归找“根”
  7. p = p->right;
  8. }
  9. cout<<t->val<<" ";
  10. }

左孩子右兄弟表示的树的层次遍历

每找到一个孩子时,迭代的把它的兄弟全部找出来,对每个结点都这样处理。

最后的结果按行来打印。

  1. //左孩子右兄弟表示的树的层次遍历
  2. void levelOrder(Tree& t){
  3. if(t == NULL) return;
  4. queue<TreeNode*> q;
  5. TreeNode* p;
  6. q.push(t);
  7. while(!q.empty()){
  8. int width = q.size();
  9. for(int i = 0;i < width;i ++){
  10. p = q.front();
  11. q.pop();
  12. cout<<p->val<<" ";
  13. p = p->left;
  14. while(p != NULL){
  15. q.push(p);
  16. p = p->right;
  17. }
  18. }
  19. cout<<endl;
  20. }
  21. }

左孩子右兄弟表示的树的宽度

与二叉树非递归找宽度的原理完全相同,既然可以按层打印,就可以比较记录最大的宽度。

  1. //左孩子右兄弟表示的树的宽度
  2. int Width(Tree& t){
  3. if(t == NULL) return 0;
  4. queue<TreeNode*> q;
  5. TreeNode* p;
  6. int max = 0;
  7. q.push(t);
  8. while(!q.empty()){
  9. int width = q.size();
  10. for(int i = 0;i < width;i ++){
  11. p = q.front();
  12. q.pop();
  13. p = p->left;
  14. while(p != NULL){
  15. q.push(p);
  16. p = p->right;
  17. }
  18. }
  19. max = max < width ? width : max;
  20. }
  21. return max;
  22. }

在以t为根的树中找结点p的双亲

循长子的兄弟链,递归在子树中搜索。

  1. //在以t为根的树中找结点p的双亲
  2. TreeNode* findParent(Tree& t,TreeNode* p){
  3. if(t == NULL || p ==NULL) return NULL;
  4. TreeNode* q = t->left;
  5. TreeNode* s;
  6. //循长子的兄弟链,递归在子树中搜索
  7. while(q != NULL && q != p){
  8. if(s = findParent(p,q) != NULL) return s; //找到双亲,返回
  9. q = q->right;
  10. }
  11. if(q != NULL && q == p) return t; //找到双亲
  12. else return NULL; //未找到
  13. }

树采用先序构造,大家可以自己画一下。

完整代码如下:

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<queue>
  4. using namespace std;
  5. //结点定义
  6. typedef struct node{
  7. char val;
  8. struct node* left; //左孩子
  9. struct node* right; //右兄弟
  10. }TreeNode,*Tree;
  11. //左孩子右兄弟表示的树的高度
  12. int Height(Tree& t){
  13. if(t == NULL) return 0;
  14. return Height(t->left) + 1 > Height(t->right) ? Height(t->left) + 1 : Height(t->right);
  15. }
  16. //左孩子右兄弟表示的树的叶子结点数
  17. int Count(Tree& t){
  18. if(t == NULL) return 0;
  19. if(t->left == NULL) return 1;
  20. return Count(t->left) + Count(t->right);
  21. }
  22. //总的结点数
  23. int CountSum(Tree& t){
  24. if(t == NULL) return 0;
  25. return CountSum(t->left) + CountSum(t->right) + 1;
  26. }
  27. //树的先根遍历
  28. void preOrder(Tree& t){
  29. if(t == NULL) return;
  30. cout<<t->val<<" ";
  31. TreeNode* p = t->left;
  32. while(p != NULL){
  33. preOrder(p); //递归找“根”
  34. p = p->right;
  35. }
  36. }
  37. //树的后根遍历
  38. void PostOrder(Tree& t){
  39. if(t == NULL) return;
  40. TreeNode* p = t->left;
  41. while(p != NULL){
  42. PostOrder(p); //递归找“根”
  43. p = p->right;
  44. }
  45. cout<<t->val<<" ";
  46. }
  47. //二叉树的层次遍历
  48. void levelOrderTraverse(Tree& t){
  49. if(t == NULL) return;
  50. queue<TreeNode*> q;
  51. TreeNode* p;
  52. q.push(t);
  53. while(!q.empty()){
  54. int width = q.size();
  55. for(int i = 0;i < width;i ++){
  56. p = q.front();
  57. q.pop();
  58. cout<<p->val<<" ";
  59. if(p->left) q.push(p->left);
  60. if(p->right) q.push(p->right);
  61. }
  62. cout<<endl;
  63. }
  64. }
  65. //左孩子右兄弟表示的树的层次遍历
  66. void levelOrder(Tree& t){
  67. if(t == NULL) return;
  68. queue<TreeNode*> q;
  69. TreeNode* p;
  70. q.push(t);
  71. while(!q.empty()){
  72. int width = q.size();
  73. for(int i = 0;i < width;i ++){
  74. p = q.front();
  75. q.pop();
  76. cout<<p->val<<" ";
  77. p = p->left;
  78. while(p != NULL){
  79. q.push(p);
  80. p = p->right;
  81. }
  82. }
  83. cout<<endl;
  84. }
  85. }
  86. //左孩子右兄弟表示的树的宽度
  87. int Width(Tree& t){
  88. if(t == NULL) return 0;
  89. queue<TreeNode*> q;
  90. TreeNode* p;
  91. int max = 0;
  92. q.push(t);
  93. while(!q.empty()){
  94. int width = q.size();
  95. for(int i = 0;i < width;i ++){
  96. p = q.front();
  97. q.pop();
  98. p = p->left;
  99. while(p != NULL){
  100. q.push(p);
  101. p = p->right;
  102. }
  103. }
  104. max = max < width ? width : max;
  105. }
  106. return max;
  107. }
  108. //先序遍历构造树
  109. void CreateTree(Tree& t){
  110. char x;
  111. cin>>x;
  112. if(x == '#') t = NULL;
  113. else{
  114. t = new TreeNode;
  115. t->val = x;
  116. CreateTree(t->left);
  117. CreateTree(t->right);
  118. }
  119. }
  120. //在以t为根的树中找结点p的双亲
  121. TreeNode* findParent(Tree& t,TreeNode* p){
  122. if(t == NULL || p ==NULL) return NULL;
  123. TreeNode* q = t->left;
  124. TreeNode* s;
  125. //循长子的兄弟链,递归在子树中搜索
  126. while(q != NULL && q != p){
  127. if((s = findParent(p,q)) != NULL) return s; //找到双亲,返回
  128. q = q->right;
  129. }
  130. if(q != NULL && q == p) return t; //找到双亲
  131. else return NULL; //未找到
  132. }
  133. int main(){
  134. Tree t;
  135. CreateTree(t);
  136. /*
  137. a b d # # e # # #
  138. */
  139. cout<<"用二叉树表示的树层次遍历:"<<endl;
  140. levelOrderTraverse(t);
  141. cout<<endl;
  142. cout<<"左孩子右兄弟表示的树的层次遍历:"<<endl;
  143. levelOrder(t);
  144. cout<<endl;
  145. cout<<"左孩子右兄弟表示的树的宽度:"<<endl;
  146. cout<<Width(t)<<endl;
  147. cout<<"左孩子右兄弟表示的树的高度 :"<<endl;
  148. cout<<Height(t)<<endl;
  149. cout<<"左孩子右兄弟表示的树的叶子结点数:"<<endl;
  150. cout<<Count(t)<<endl;
  151. cout<<"树的总结点数:"<<endl;
  152. cout<<CountSum(t)<<endl;
  153. cout<<"树的先根遍历:"<<endl;
  154. preOrder(t);
  155. cout<<endl;
  156. cout<<"树的后根遍历:"<<endl;
  157. PostOrder(t);
  158. cout<<endl;
  159. }

运行结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/692688
推荐阅读
相关标签
  

闽ICP备14008679号