• 【王道数据结构编程题】- 二叉树编程练习


    目录

    1.写出在中序线索二叉树中查找指定节点在后序的前驱节点的算法。

    2.二叉树的带权路径长度(WPL)是二叉树中所有叶节点的带权路径长度之和,给定一颗二叉树T,采用二叉链表存储,节点结构为

    left weight right

    其中叶节点的weight域保存该节点的非负权值,设root为指向T的根节点的指针。设计求T的WPL的算法。

    3.设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式。

    4.编写程序求以孩子兄弟表示法存储的森林的叶子节点数 

    5. 以孩子兄弟链表为存储结构 设计递归算法求树的深度

    6.已知一棵树的层次序列以及每个节点的度 编写算法构造此树的孩子-兄弟链表


    1.写出在中序线索二叉树中查找指定节点在后序的前驱节点的算法。

    1. //在中序线索二叉树中查找指定节点在后序的前驱节点的算法
    2. #include<iostream>
    3. using namespace std;
    4. //线索二叉树节点的结构体
    5. typedef struct treenode{
    6. //节点的值
    7. char data;
    8. //节点的左右孩子指针
    9. struct treenode *lchild,*rchild;
    10. //ltag rtag
    11. int ltag,rtag;
    12. }treenode,*tree;
    13. //建树 赋值节点
    14. void buildtree(tree &t)
    15. {
    16. char ch;
    17. cin>>ch;
    18. if(ch=='#') t=NULL;
    19. else
    20. {
    21. //对节点进行内存分配
    22. t=(treenode *)malloc(sizeof(treenode));
    23. //对节点进行赋值
    24. t->data=ch;
    25. //初始化 左右孩子节点为空
    26. t->lchild=NULL;
    27. t->rchild=NULL;
    28. t->ltag=t->rtag=0;
    29. //递归去赋值左右子树
    30. buildtree(t->lchild);
    31. buildtree(t->rchild);
    32. }
    33. }
    34. tree pre;
    35. //遍历二叉树的保留的前驱节点
    36. //中序线索化
    37. void zx(tree &t)
    38. {
    39. //递归的条件
    40. if(t)
    41. {
    42. //向左延申 找叶子节点
    43. zx(t->lchild);
    44. if(t->lchild==NULL)//左孩子为空
    45. {
    46. t->ltag=1;
    47. t->lchild=pre;
    48. }
    49. else t->ltag=0;
    50. if(pre!=NULL&&pre->rchild==NULL)//没有右孩子
    51. {
    52. pre->rtag=1;//前驱节点有后继节点
    53. pre->rchild=t;//后继节点指向当前
    54. }
    55. pre=t;//更新前驱节点
    56. zx(t->rchild);
    57. }
    58. }
    59. //找后继的前驱节点
    60. tree Inpostpre(tree t,treenode *p)
    61. {
    62. //结果指针
    63. treenode *q;
    64. //该节点有右孩子 结果就是右孩子
    65. if(p->rtag==0) q=p->rchild;
    66. //该节点没有右孩子的情况下 有左孩子 结果就是左孩子
    67. else if(p->ltag==NULL) q=NULL;
    68. //其他
    69. else
    70. {
    71. //不断沿着线索找到祖先节点
    72. while(p->ltag==1&&p->lchild!=NULL)
    73. p=p->lchild;
    74. if(p->ltag==0) q=p->lchild;
    75. //若找到祖先节点 且有左孩子 结果就是左孩子
    76. else q=NULL;
    77. //最后就是没有后序前驱
    78. }
    79. return q;
    80. }
    81. //主函数 测试
    82. int main()
    83. {
    84. tree t;
    85. buildtree(t);
    86. zx(t);
    87. cout<<Inpostpre(t,t->rchild)->data<<endl;
    88. return 0;
    89. }
    90. /*
    91. A
    92. B C
    93. D E F G
    94. */
    95. //ABD##E##CF##G##

    2.二叉树的带权路径长度(WPL)是二叉树中所有叶节点的带权路径长度之和,给定一颗二叉树T,采用二叉链表存储,节点结构为

    left weight right

    其中叶节点的weight域保存该节点的非负权值,设root为指向T的根节点的指针。设计求T的WPL的算法。

    1. //带权路径长度之和
    2. #include<iostream>
    3. using namespace std;
    4. //结构体
    5. typedef struct treenode{
    6. //节点的值
    7. char weight;
    8. //节点的左右孩子指针
    9. struct treenode *lchild,*rchild;
    10. }treenode,*tree;
    11. //建树
    12. void buildtree(tree &t)
    13. {
    14. char ch;
    15. cin>>ch;
    16. if(ch=='#') t=NULL;
    17. else
    18. {
    19. //对节点进行内存分配
    20. t=(treenode *)malloc(sizeof(treenode));
    21. //对节点进行赋值
    22. t->weight=ch;
    23. //初始化 左右孩子节点为空
    24. t->lchild=NULL;
    25. t->rchild=NULL;
    26. //递归去赋值左右子树
    27. buildtree(t->lchild);
    28. buildtree(t->rchild);
    29. }
    30. }
    31. //计算wpl
    32. int wplpre(tree t,int deep)
    33. {
    34. //静态变量 存储结果值并函数末尾返回
    35. static int ans =0;
    36. //若是叶子节点 累加值
    37. if(t->lchild==NULL&&t->rchild==NULL)
    38. ans+=(deep*((t->weight)-'0'));
    39. if(t->lchild!=NULL)
    40. wplpre(t->lchild,deep+1);
    41. //若不是叶子节点 递归遍历左子树找到叶子节点同时层数+1
    42. if(t->rchild!=NULL)
    43. wplpre(t->rchild,deep+1);
    44. //若不是叶子节点 递归遍历左子树找到叶子节点同时层数+1
    45. return ans;
    46. }
    47. //主函数 测试
    48. int main()
    49. {
    50. tree t;
    51. buildtree(t);
    52. cout<<wplpre(t,0)<<endl;
    53. return 0;
    54. }
    55. /*
    56. 1
    57. 2 3
    58. 4 5 6 7
    59. 124##5##36##7##
    60. ans = (4+5+6+7)*2=44
    61. */

    3.设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式。

    1. //表达式树转换为中缀表达式
    2. #include<iostream>
    3. using namespace std;
    4. //结构体
    5. typedef struct treenode{
    6. //节点的值
    7. char data;
    8. //节点的左右孩子指针
    9. struct treenode *lchild,*rchild;
    10. }treenode,*tree;
    11. //建树
    12. void buildtree(tree &t)
    13. {
    14. char ch;
    15. cin>>ch;
    16. if(ch=='#') t=NULL;
    17. else
    18. {
    19. //对节点进行内存分配
    20. t=(treenode *)malloc(sizeof(treenode));
    21. //对节点进行赋值
    22. t->data=ch;
    23. //初始化 左右孩子节点为空
    24. t->lchild=NULL;
    25. t->rchild=NULL;
    26. //递归去赋值左右子树
    27. buildtree(t->lchild);
    28. buildtree(t->rchild);
    29. }
    30. }
    31. //转换函数
    32. void toexp(tree t,int deep)
    33. {
    34. if(t==NULL) return;
    35. else if(t->lchild==NULL&&t->rchild==NULL)
    36. {
    37. cout<<t->data;
    38. }
    39. else
    40. {
    41. if(deep>1) cout<<"(";
    42. toexp(t->lchild,deep+1);
    43. cout<<t->data;
    44. toexp(t->rchild,deep+1);
    45. if(deep>1) cout<<")";
    46. }
    47. }
    48. //主函数 测试
    49. int main()
    50. {
    51. tree t;
    52. buildtree(t);
    53. toexp(t,1);
    54. return 0;
    55. }
    56. /*
    57. *
    58. + *
    59. a b c -
    60. *+a##b##*c##-#d##
    61. +
    62. * -
    63. a b -
    64. c d
    65. +*a##b##-#-c##d##
    66. +
    67. a b
    68. +a##b##
    69. */

     

    4.编写程序求以孩子兄弟表示法存储的森林的叶子节点数 

    1. //求以孩子兄弟表示法存储的森林的叶子节点数
    2. #include<iostream>
    3. using namespace std;
    4. //结构体
    5. typedef struct treenode{
    6. //节点的值
    7. char data;
    8. //左孩子域 右兄弟域 指向
    9. struct treenode *child,*rbro;
    10. }treenode,*tree;
    11. //建树
    12. void buildtree(tree &t)
    13. {
    14. char ch;
    15. cin>>ch;
    16. if(ch=='#') t=NULL;
    17. else
    18. {
    19. //对节点进行内存分配
    20. t=(treenode *)malloc(sizeof(treenode));
    21. //对节点进行赋值
    22. t->data=ch;
    23. //初始化 左右孩子节点为空
    24. t->child=NULL;
    25. t->rbro=NULL;
    26. //递归去赋值左右子树
    27. buildtree(t->child);
    28. buildtree(t->rbro);
    29. }
    30. }
    31. //递归找叶子节点
    32. int leaves(tree t)
    33. {
    34. //空节点 返回0
    35. if(t==NULL) return 0;
    36. //孩子为空 即左孩子域为空 为叶子节点 结果+1还要加上右兄弟子树的叶子节点
    37. if(t->child==NULL) return 1+leaves(t->rbro);
    38. //有孩子 结果为左孩子子树和右兄弟子树的叶子节点个数之和
    39. else return leaves(t->child)+leaves(t->rbro);
    40. }
    41. //主函数 测试
    42. int main()
    43. {
    44. tree t;
    45. buildtree(t);
    46. cout<<leaves(t)<<endl;
    47. return 0;
    48. }
    49. /*
    50. A
    51. B F
    52. D C G
    53. E
    54. ABD#E##C##FG###
    55. */

     

    5. 以孩子兄弟链表为存储结构 设计递归算法求树的深度

    1. //以孩子兄弟链表为存储结构 设计递归算法求树的深度
    2. #include<iostream>
    3. using namespace std;
    4. //结构体
    5. typedef struct treenode{
    6. //节点的值
    7. char data;
    8. //左孩子域 右兄弟域 指向
    9. struct treenode *child,*rbro;
    10. }treenode,*tree;
    11. //建树
    12. void buildtree(tree &t)
    13. {
    14. char ch;
    15. cin>>ch;
    16. if(ch=='#') t=NULL;
    17. else
    18. {
    19. //对节点进行内存分配
    20. t=(treenode *)malloc(sizeof(treenode));
    21. //对节点进行赋值
    22. t->data=ch;
    23. //初始化 左右孩子节点为空
    24. t->child=NULL;
    25. t->rbro=NULL;
    26. //递归去赋值左右子树
    27. buildtree(t->child);
    28. buildtree(t->rbro);
    29. }
    30. }
    31. int max(int a,int b)
    32. {
    33. if (a<b) return b;
    34. else return a;
    35. }
    36. //递归计算深度
    37. int height(tree t)
    38. {
    39. if(t==NULL) return 0;
    40. else
    41. {
    42. //递归计算左孩子子树高度
    43. int l=height(t->child);
    44. //递归计算右兄弟子树高度
    45. int r=height(t->rbro);
    46. return max(l+1,r);
    47. }
    48. }
    49. //主函数 测试
    50. int main()
    51. {
    52. tree t;
    53. buildtree(t);
    54. cout<<height(t)<<endl;
    55. return 0;
    56. }
    57. /*
    58. A
    59. B
    60. D C
    61. E F
    62. ABD#E##CF####
    63. */

    6.已知一棵树的层次序列以及每个节点的度 编写算法构造此树的孩子-兄弟链表

    1. //已知一棵树的层次序列以及每个节点的度 编写算法构造此树的孩子-兄弟链表
    2. #include<iostream>
    3. using namespace std;
    4. //结构体
    5. typedef struct treenode{
    6. //节点的值
    7. char data;
    8. //左孩子域 右兄弟域 指向
    9. struct treenode *child,*rbro;
    10. }treenode,*tree;
    11. //构建链表
    12. void creat(tree &t,char e[],int degree[],int n)
    13. {
    14. //动态申请节点数组
    15. tree *point=new tree[10];
    16. int i;
    17. for(i=0;i<n;i++)
    18. {
    19. //给每个节点动态申请内存
    20. point[i]=(treenode *)malloc(sizeof(treenode));
    21. //给每个节点初始化 初始值为给的字母和对应的左右指针初始化为空
    22. point[i]->data=e[i];
    23. point[i]->child=point[i]->rbro=NULL;
    24. }
    25. //孩子节点序号
    26. int k=0;
    27. //按照给的节点顺序访问节点
    28. for(i=0;i<n;i++)
    29. {
    30. //获取该节点的度
    31. int d=degree[i];
    32. //如果有度,说明有孩子节点
    33. if(d)
    34. {
    35. //孩子序号递增
    36. k++;
    37. //将第一个孩子作为自己的左孩子节点
    38. point[i]->child=point[k];
    39. //剩余的孩子 每个节点依次为前一个节点的兄弟节点
    40. for(int j=2;j<=d;j++)
    41. {
    42. //孩子序号递增
    43. k++;
    44. //前一个节点的右兄弟指针指向现在孩子序号的节点
    45. point[k-1]->rbro=point[k];
    46. }
    47. }
    48. }
    49. t=point[0];
    50. //链表的头为第一个节点
    51. delete [] point;
    52. //动态申请的内存要进行一个释放 防止内存泄露
    53. }
    54. //输出最后孩子兄弟表示的树的先序序列进行验证
    55. void disp(tree t)
    56. {
    57. if(t)
    58. {
    59. cout<<t->data<<" ";
    60. disp(t->child);
    61. disp(t->rbro);
    62. }
    63. }
    64. //主函数 测试
    65. int main()
    66. {
    67. tree t;
    68. //层次遍历序列
    69. char e[8]="ABCDEFG";
    70. //每个节点度数数组
    71. int degree[8]={3,2,1,0,0,0,0};
    72. //构造这样的函数
    73. creat(t,e,degree,7);
    74. //输出这样的二叉树验证
    75. disp(t);
    76. return 0;
    77. }
    78. /*
    79. A
    80. B C D
    81. E F G
    82. A
    83. B
    84. E C
    85. F G D
    86. ABCDEFG
    87. 3,2,1,0,0,0,0
    88. 先序:A B E F C G D
    89. */

  • 相关阅读:
    有关服务器虚拟化的常见问题解答
    redis的持久化
    Python的常用排序算法实现
    ASP.NET实现的教研室管理系统(提供源码和报告)
    甩出11张图-让我们来构想(实现)一个倒排索引
    揭秘一线大厂Redis面试高频考点(3万字长文、吐血整理)
    Java WebSocket框架
    世界上最伟大的女程序员
    triton 客戶端用https协议访问服务
    二、线程常用方法
  • 原文地址:https://blog.csdn.net/m0_56051805/article/details/125434425