• 北京化工大学数据结构2022/10/27作业 题解


    目录

    问题 A: 二叉树的性质

    问题 B: 二叉树的节点

     问题 C: 满二叉树

     问题 D: 完全二叉树的节点序号

    -----------------------------------分割线------------------------------------------

    问题 E: 二叉树的深度

    问题 F: 数据结构作业04 -- 二叉树的输入

    递归版

    迭代版

    问题 G: 给定前序遍历序手动构造二叉树-附加代码模式


    问题 A: 二叉树的性质

    答案非常简单就是输出n-1

    但怎么证的呢?

    我们不妨先论证一下总的度数和节点数的关系(这里的度指的是子节点数)

    最开始我们的树只有一个根节点,而每派生出一个“度”,也就派生出了一个子节点

    所以在这之后派生出的总度数量是等于所以子节点数量的

    在加上根节点,也就得到了下面式子

    节点总数=总度数+1

    而左边节点度数可以写成  度为0的节点+度为1的节点+度为2的节点

    右边可以写成   2*度为2的节点+1*度为1的节点+1

    上式即为 度为0的节点+度为1的节点+度为2的节点= 2*度为2的节点+1*度为1的节点+1

    两边一合并

    度为2的节点+1=度为0的节点

    也就证出来了

    代码如下

    cpp

    1. int n;
    2. cin>>n;
    3. cout<-1<

    python

    1. n = int(input())
    2. print(n-1)

    问题 B: 二叉树的节点

    二叉树的深度取决于最深的节点

    最少节点我们只要一条路走到黑或者之字形走,如下图

    这样最少节点数就等于深度

    (题外话)

    也就是说基于二叉树实现的搜索树最坏情况会退化为链表,而在单链表中查找和指定删除都为n^{2}

    边缘性能很差,这也就有了之后AVL,红黑树的故事 

    最多也很简单

    只需要每层都满节点就好了

    也就是1+2+4....2^{n-1}

    也就等于2^{n}-1

     cpp代码

    1. int n;
    2. cin>>n;
    3. cout<' '<<pow(2,n)-1;

    python代码

    1. h=int(input())
    2. ma = pow(2,h)-1
    3. print(h,ma)

     问题 C: 满二叉树

    这道题同上了

    满二叉树就是节点最多的时候

    判断即可

    cpp代码 

    1. int h,n;
    2. while(cin>>h>>n)
    3. {
    4. if (n==pow(2,h)-1) cout<<"YES"<
    5. else cout<<"NO"<
    6. }

    python代码

    1. while 1:
    2. h,n=map(int,input().split())
    3. if pow(2,h)-1 == n:
    4. print('YES')
    5. else:
    6. print('NO')

     问题 D: 完全二叉树的节点序号

    我们用数组在存这种二叉堆结构有一个默认的方式,例如存线段树

    左儿子等于父亲*2,右儿子等于父亲*2+1

    例如存一棵value值如下图的7个节点的满二叉树

    在数组中为

    这样a[2]的儿子就是left:a[2*2],right:a[2*2+1]

    也就是a[4]和a[5]

    这题下标是从0开始,加个偏移量即可

    代码如下

    1. int n;
    2. while(cin>>n){
    3. if(n==0) cout<<"-1 1 2\n";
    4. else cout<<(n-1)/2<<" "<<2*n+1<<" "<<2*n+2<<'\n';
    5. }

    -----------------------------------分割线------------------------------------------

    以下二叉树的前中后序遍历

    思路详解见(2条消息) (数据结构)如何手搓一棵二叉树?_lxrrrrrrrr的博客-CSDN博客

    我们只要实现一个简单的就好

    问题 E: 二叉树的深度

    先建树,在找深度

    建树:他提供带虚节点前序遍历,前序遍历是 根左右

    所以我们按照根左右的方式重构树即可,遇到虚节点时结束,代表当前点无节点

    找深度时每个节点的dep=max(dep[left],dep[right])+1

    从底层节点递归上来即可

    代码如下

    1. #include
    2. using namespace std;
    3. int ind;
    4. class node{
    5. public:
    6. char data;
    7. int dep;
    8. node* left;
    9. node* right;
    10. };
    11. class bintree{
    12. public:
    13. node* __root;
    14. void createtree(node* &T,string s);
    15. int updatadep(node *T);
    16. };
    17. void bintree::createtree(node* &T,string s){
    18. char data=s[ind];
    19. ind++;
    20. if(data=='#'){
    21. T=nullptr;
    22. }
    23. else{
    24. T=new node;
    25. T->data=data;
    26. createtree(T->left,s);
    27. createtree(T->right,s);
    28. }
    29. }
    30. int bintree::updatadep(node *T){
    31. int L,R;
    32. if(T!=NULL){
    33. L=updatadep(T->left);
    34. R=updatadep(T->right);
    35. T->dep=L>R?L+1:R+1;
    36. return T->dep;
    37. }
    38. return 0;
    39. }
    40. signed main(){
    41. bintree tree;
    42. string str;
    43. int T;
    44. cin>>T;
    45. while(T--){
    46. cin>>str;
    47. bool fl=false;
    48. for(auto t:str){
    49. if(t!='#'){
    50. fl=true;
    51. break;
    52. }
    53. }
    54. if(!fl){cout<<"0\n";continue;}
    55. ind=0;
    56. tree.createtree(tree.__root,str);
    57. cout<updatadep(tree.__root)<<'\n';
    58. }
    59. }

    问题 F: 数据结构作业04 -- 二叉树的输入

    建树前一道题已经建过了

    这里主要说下中后序遍历

    中序遍历我给出了两种方式

    递归版和迭代版

    递归版

    中序遍历是按照 左--根--右 的方式遍历

    递归版写起来特别简单

    这样在回溯的时候就会按照中序遍历遍历这棵树

    前后序遍历的递归版也就是调换一下顺序

    迭代版

    同样是从根节点开始,不断地沿着左子树向下走。不同的是,这里向下行进的过程中不能访问当前结点,只有等到当前结点的左子树完成访问时,才能轮到当前结点,因此想到引入一个栈来实现延迟缓冲的功能。走到最左侧的第一个没有左子树的叶子结点时,没有左子树也相当于已经完成了左子树的访问,于是随后便访问当前结点x,然后转入到x的右子树。

    当x的右子树完成访问时,即标志着以x为根的子树访问完毕,随机访问x的父亲结点,然后访问x的父亲的右子结点。x的右兄弟结点访问完毕时,即标志着以x的父亲的根的子树访问完毕,随即访问x父亲的父亲,然后是x父亲的父亲的父亲...
     

    后序遍历的详解(2条消息) (数据结构)如何手搓一棵二叉树?_lxrrrrrrrr的博客-CSDN博客

    goAlongLeft函数的作用是对于每一个节点,一直向左走,这一条左链都压入栈

    具体实现:对于每一个节点,先一直向左走,将他的所有左儿子都压入栈,之后每一个左儿子

    按顺序出栈,遍历此节点,再遍历此节点的右节点,之后下一个左儿子出栈.....

     

    代码如下:

    1. #include
    2. using namespace std;
    3. int ind;
    4. class node{
    5. public:
    6. char data;
    7. node* left;
    8. node* right;
    9. };
    10. class bintree{
    11. public:
    12. node* __root;
    13. void createtree(node* &T,string s);
    14. void visit(node* T){if(T->data!='#') cout<data;}
    15. void inorder(node* T);
    16. void postorder(node* T);
    17. void levelorder(node* T);
    18. void goalongleft(stack &S,node* now);
    19. void inorder_it(node* T);
    20. };
    21. void bintree::createtree(node* &T,string s){
    22. char data=s[ind];
    23. ind++;
    24. if(data=='#'){
    25. T=nullptr;
    26. }
    27. else{
    28. T=new node;
    29. T->data=data;
    30. createtree(T->left,s);
    31. createtree(T->right,s);
    32. }
    33. }
    34. void bintree::inorder(node* T){
    35. if(T!=nullptr){
    36. inorder(T->left);
    37. visit(T);
    38. inorder(T->right);
    39. }
    40. }
    41. void bintree::goalongleft(stack &S,node* now){
    42. node* curr=now;
    43. while(curr!=nullptr){
    44. S.push(curr);
    45. curr=curr->left;
    46. }
    47. }
    48. void bintree::inorder_it(node* T){
    49. stack S;
    50. node* curr=T;
    51. while(1){
    52. goalongleft(S,curr);
    53. if(S.empty()) break;
    54. curr=S.top();
    55. S.pop();
    56. visit(curr);
    57. curr=curr->right;
    58. }
    59. }
    60. void bintree::postorder(node* T){
    61. if(T!=nullptr){
    62. postorder(T->left);
    63. postorder(T->right);
    64. visit(T);
    65. }
    66. }
    67. void bintree::levelorder(node* T){
    68. queue q;
    69. q.push(this->__root);
    70. while(!q.empty()){
    71. node* top=q.front();
    72. q.pop();
    73. visit(top);
    74. if(top->left) q.push(top->left);
    75. if(top->right) q.push(top->right);
    76. }
    77. }
    78. signed main(){
    79. bintree tree;
    80. string str;
    81. while(cin>>str){
    82. bool fl=false;
    83. for(auto t:str){
    84. if(t!='#'){
    85. fl=true;
    86. break;
    87. }
    88. }
    89. if(!fl){cout<<"\n";continue;}
    90. ind=0;
    91. tree.createtree(tree.__root,str);
    92. tree.inorder(tree.__root);
    93. cout<<" ";
    94. // tree.inorder_it(tree.__root);
    95. // cout<
    96. tree.postorder(tree.__root);
    97. cout<<" ";
    98. tree.levelorder(tree.__root);
    99. cout<<'\n';
    100. }
    101. }

    问题 G: 给定前序遍历序手动构造二叉树-附加代码模式

    随便编一个就行

    1. using namespace std;
    2. struct BiNode
    3. {
    4. string data;
    5. BiNode *lchild, *rchild;
    6. };
    7. typedef BiNode *BiTree;
    8. int InitBiTree(BiTree &T)
    9. {
    10. T = NULL;
    11. return 0;
    12. }
    13. void ManuallyCreateTree(BiTree & T){
    14. T = new BiNode();
    15. T->data = "a";
    16. BiNode* n1 = new BiNode();
    17. n1->data = "b";
    18. BiNode* n2 = new BiNode();
    19. n2->data = "c";
    20. T->lchild = n1;
    21. T->rchild = n2;
    22. BiNode* p = new BiNode();
    23. p->data = "d";
    24. n1->lchild = p;
    25. BiNode* p1 = new BiNode();
    26. p1->data = "e";
    27. n1->rchild = NULL;
    28. n2->lchild = p1;
    29. BiNode* p2 = new BiNode();
    30. p2->data = "f";
    31. n2->rchild = p2;
    32. }

    C语言毕竟不是面向过程的语言,用C写这种数据结构简直坐牢

    毕竟高内聚低耦合的cpp写出来很养眼

  • 相关阅读:
    JVM 面试题总结
    敏捷开发中,Sprint回顾会的目的
    Android自定义注解实现一键校验实体类参数
    【OPENCV_系列电子PDF图书连载】计算机视觉从入门到精通完整学习路线专栏
    SparkSQL执行流程与Catalyst优化器
    Salesforce正在推出AI功能,传统的项目文档管理还需要么?
    每日十(?)题之20220903
    基于python的汽车数据可视化、推荐及预测系统
    0基础学习PyFlink——Map和Reduce函数处理单词统计
    【Java】环境配置以及快速切换环境的技巧和方法
  • 原文地址:https://blog.csdn.net/m0_61735576/article/details/127542214