当前位置:   article > 正文

北京化工大学数据结构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<<n-1<<endl;

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<<n<<' '<<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"<<endl;
  5. else cout<<"NO"<<endl;
  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<bits/stdc++.h>
  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<<tree.updatadep(tree.__root)<<'\n';
  58. }
  59. }

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

建树前一道题已经建过了

这里主要说下中后序遍历

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

递归版和迭代版

递归版

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

递归版写起来特别简单

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

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

迭代版

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

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

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

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

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

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

 

代码如下:

  1. #include<bits/stdc++.h>
  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<<T->data;}
  15. void inorder(node* T);
  16. void postorder(node* T);
  17. void levelorder(node* T);
  18. void goalongleft(stack<node*> &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<node*> &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<node*> 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<node*> 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<<endl;
  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写出来很养眼

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

闽ICP备14008679号