当前位置:   article > 正文

7-2 树的遍历 (PTA-数据结构)_树的遍历pta

树的遍历pta

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

  1. 7
  2. 2 3 1 5 7 6 4
  3. 1 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

提交结果: 


思路分析:

        面对该题,博主起初打算根据上一题(根据后序和中序遍历输出先序遍历)的思路,先设置一个用数组存储的先序遍历结果,再通过某些数学关系,用先序遍历来找出层序遍历,后来发现似乎没有必要联系,便退回到起初,打算类同于在后序和中序遍历中创建二叉链表储存的树。

        第一个版本:因为之前已经有后序和中序得到先序的代码,所以打算用先序来创建一棵二叉树,如下:

  1. void makePre(int Tree[], int post[], int min[], int root, int fin, int start){
  2. if((fin <= start)||(root<0)) {
  3. return;
  4. }
  5. int i;
  6. int head = post[root];
  7. Tree[flag] = head;
  8. flag++;
  9. for(i=start; i<fin;i++) {
  10. if (min[i] == head) {
  11. break;
  12. }
  13. }
  14. makePre(Tree,post,min,root-fin+i,i,start);
  15. makePre(Tree,post,min,root-1,fin,i+1);
  16. }
  17. TreeNode* buildTree(int preorder[], int start, int end) {
  18. if (start > end) {
  19. return NULL;
  20. }
  21. TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
  22. root->val = preorder[start];
  23. int i = start + 1;
  24. while (i <= end && preorder[i] < root->val) {
  25. i++;
  26. }
  27. root->left = buildTree(preorder, start + 1, i - 1);
  28. root->right = buildTree(preorder, i, end);
  29. return root;
  30. }
  31. void LevelOrder(TreeNode *root, int num) //二叉树的层次遍历
  32. {
  33. TreeNode *temp[100000]; //创建pTreeNode指针类型的指针数组(真想不出来)
  34. int in = 0;
  35. int out = 0;
  36. temp[in++] = root; //先保存二叉树根节点
  37. int n = 0;
  38. while (in > out)
  39. {
  40. if (temp[out])
  41. {
  42. if(n == num-1)
  43. printf("%d",temp[out]->val);
  44. else printf("%d ",temp[out]->val);
  45. temp[in++] = temp[out]->left;
  46. temp[in++] = temp[out]->right;
  47. n++;
  48. }
  49. out++;
  50. }
  51. }

(固定且有效的算法)

        先序创建二叉树buildTree:此算法是根据结点的值来判定左右子树的,因此其中的循环判断第一个大于根节点的值再去进行下面的遍历,从而继续创建左右子树(可能是造成此种思路失败原因);

        LevelOrder层序遍历:使用了队列来储存正在遍历的结点,之后若不空,打印其值,并再将其左右孩子入队,做到一层一层的打印出来值。

        但是在上面思路的这种情况下,pta最后一个检查点无法通过,找不到bug的存在,因此只得求助于其他博客,我得到了用中序和后序直接创建树的代码,进行了二次尝试:

  1. TreeNode* buildTree(int min[], int post[], int n){
  2. if(!n)
  3. return NULL;
  4. TreeNode *T = (TreeNode *)malloc(sizeof(struct TreeNode));
  5. T->val = post[n-1]; //后序遍历的最后一个节点就是树的根节点
  6. T->left = T->right = NULL;
  7. //从中序遍历中找到根节点的位置
  8. int index;
  9. for(index=0; index<n; index++) {
  10. if(min[index] == post[n-1]) break;
  11. }
  12. T->left = buildTree(min, post, index);
  13. T->right = buildTree(min+index+1, post+index, n-index-1);
  14. return T;
  15. }

        中序后序创建树:该代码算法思想和上面我们提到用后序和中序创建树的思想很像,具体再递归传参,但是此算法直接通过偏移量传数组,上面makePre函数则是通过了两个int型变量存下标,但是区别不大。之后将该代码段替换掉我上面创建先序遍历数组,和通过先序数组创建树的代码,成功解决问题,没有错误通过。


代码内容:

  1. //
  2. // Created by DDD on 2023/11/20.
  3. //
  4. #include <stdio.h>
  5. #include <malloc.h>
  6. typedef struct TreeNode {
  7. int val;
  8. struct TreeNode *left;
  9. struct TreeNode *right;
  10. } TreeNode;
  11. TreeNode* buildTree(int min[], int post[], int n){
  12. if(!n)
  13. return NULL;
  14. TreeNode *T = (TreeNode *)malloc(sizeof(struct TreeNode));
  15. T->val = post[n-1]; //后序遍历的最后一个节点就是树的根节点
  16. T->left = T->right = NULL;
  17. //从中序遍历中找到根节点的位置
  18. int index;
  19. for(index=0; index<n; index++)
  20. {
  21. if(min[index] == post[n-1]) break;
  22. }
  23. T->left = buildTree(min, post, index);
  24. T->right = buildTree(min+index+1, post+index, n-index-1);
  25. return T;
  26. }
  27. void LevelOrder(TreeNode *T)
  28. {
  29. if(T)
  30. {
  31. TreeNode *queue[100];
  32. int left = 0, right = 0;
  33. queue[right++] = T;
  34. while (left < right)
  35. {
  36. TreeNode *bt = queue[left++];
  37. if(bt == T)
  38. printf("%d", bt->val); //为根节点时,无空格输出
  39. else
  40. printf(" %d", bt->val);
  41. if(bt->left)
  42. queue[right++] = bt->left;
  43. if(bt->right)
  44. queue[right++] = bt->right;
  45. }
  46. }
  47. }
  48. int main(){
  49. int num;
  50. scanf("%d",&num);
  51. int post[100]; //后序
  52. int min[100]; //中序
  53. //int Tree[1000] = {0}; //先序
  54. for(int i=0; i<num;i++){
  55. scanf("%d",&post[i]);
  56. }
  57. for(int i=0; i<num;i++){
  58. scanf("%d",&min[i]);
  59. }
  60. //makePre(Tree,post,min,num - 1,num,0);
  61. TreeNode TN = *buildTree(min,post,num);
  62. LevelOrder(&TN);
  63. }

后记:

        总而言之,树往后的需要我们掌握的固定算法太多,还需要我们去亲手写一下,走走代码的整个思路。难度突然就上来了。


return 0;//载酒买花少年事

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

闽ICP备14008679号