zoukankan      html  css  js  c++  java
  • 1020. Tree Traversals (25)

    距离18号的PAT考试还有18天,最重要的是挖透做过的每一题

    (1)基本思路:

    1.建树用right数组和left保存各个节点的右左节点

    2.层次遍历

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    #define M 32
    int post[M];
    int in[M];
    int n;
    int left[M];
    int right[M];
    queue<int> q;
    
    //建树
    int built_tree(int st1,int end1,int st2,int end2,int root){
      if(st1 > end1 || st2 > end2) return 0;
      if(st1 == end1 || st2 == end2) return post[st1];
      for(int i=st2;i<=end2;i++) {
        if(root == in[i]) {
          int ne1=st1+i-st2-1;
          left[root]=built_tree(st1,ne1,st2,i-1,post[ne1]);
          right[root]=built_tree(ne1+1,end1-1,i+1,end2,post[end1-1]);
        }
      }
      return root;
    }
    
    int main() {
      scanf("%d",&n);
      
      memset(post,0,sizeof(post));
      memset(in,0,sizeof(in));
      memset(left,0,sizeof(left));
      memset(right,0,sizeof(right));
    
      for(int i=0;i<n;i++) {
        int node;
        scanf("%d",&node);
        post[i]=node;
      }
      for(int i=0;i<n;i++) {
        int node;
        scanf("%d",&node);
        in[i]=node;
      }
    
      int root=built_tree(0,n-1,0,n-1,post[n-1]);  
      /*
      printf("L:");
      for(int i=1;i<=n;i++) {
        printf("%d ",left[i]);
      }
      printf("
    R:");
      for(int i=1;i<=n;i++) {
        printf("%d ",right[i]);
      }
      printf("
    ");
      */
    //层次遍历
      q.push(root);
      int cnt=0;
      while(!q.empty()) {
        int index=q.front();
        cnt==0? printf("%d",index):printf(" %d",index); 
        q.pop();
        cnt++;
        if(left[index] != 0) {
          q.push(left[index]);
        }
        if(right[index]!=0) {
          q.push(right[index]);
        }
      }
      return 0;
    }

    (2)不建树直接用一个数组存储结果

    不过在这之前先试一下更简单的---转换成先序(根左右)

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    #define M 32
    int post[M];
    int in[M];
    int n;
    
    //start 为in中的start end同,root为post中的root
    void pre(int root,int start,int end,int cnt) {
      if(start > end) return;
      //find left subtree and right subtree
      //比如左子树不存在那么该算法会认为根为左子树的start而end则是通过根减一得到
      //所以会产生start比end大的情况
      //同理右子树不存在start为i+1而新的end为原来的end
    
      //如果是一个节点的树那么会有start=end
      //如果start end相等就是多个节点的树
      int i;
      for(i=start;i<=end;i++) {
        if(in[i]==post[root]) break;
      }
      cnt == 0? printf("%d",post[root]):printf(" %d",post[root]);
      //left subtree
      pre(root-end+i-1,start,i-1,++cnt);
      //right subtree
      pre(root-1,i+1,end,++cnt);
    }
    
    int main() {
      scanf("%d",&n);
      
      memset(post,0,sizeof(post));
      memset(in,0,sizeof(in));
      for(int i=0;i<n;i++) {
        int node;
        scanf("%d",&node);
        post[i]=node;
      }
      for(int i=0;i<n;i++) {
        int node;
        scanf("%d",&node);
        in[i]=node;
      }
      
      pre(n-1,0,n-1,0);
      return 0;
    }

    层次遍历

    技巧就是虽然不是层次遍历但是可以用index来得到对应的层次中的节点

                               1

                       |                 |

                      2                  3

                |          |         |          |

             4            5        6         7

          访问顺序虽然是1 2 4  5  3 6 7 (先序)

      但是用index从零开始记录

      访问顺序虽然没有变但是存在数组的位置却是按照层次来的 比如0位置存1    2*0+1位置 存2  2*0+2存3以后同理

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    #define M 32
    //数组开大一点不然最后一个过不去
    #define N 1000000
    int post[M];
    int in[M];
    //不能只开M的大小的数组因为空节点也会存在level中
    int level[N];
    int n;
    
    void pre(int root,int start,int end,int index) {
      if(start > end) return;
      int i;
      for(i=start;i<=end;i++) {
        if(in[i]==post[root]) break;
      }
    level[index]=post[root]; //left subtree pre(root-end+i-1,start,i-1,2*index+1); //right subtree pre(root-1,i+1,end,2*index+2); } int main() { scanf("%d",&n); memset(post,0,sizeof(post)); memset(in,0,sizeof(in)); memset(level,-1,sizeof(level)); for(int i=0;i<n;i++) scanf("%d",&post[i]); for(int i=0;i<n;i++) scanf("%d",&in[i]); pre(n-1,0,n-1,0); // 由于可能存在空节点即为-1的点所以要跳过 int cnt=0; for(int i=0;i<N;i++) { //n个节点全部打印出 if(cnt == n) break; if(level[i] == -1) continue; cnt==0? printf("%d",level[i]):printf(" %d",level[i]); cnt++; } return 0; }

  • 相关阅读:
    web开发:jquery高级
    web开发:jquery初级
    web开发:javascript之dom与bom
    web开发:javascript案例
    web开发:javascript动画
    web开发:javascript高级
    web开发:javascript操作
    web开发:javascript基础
    web开发:形变、表格及多行文本操作
    web开发:动画及阴影
  • 原文地址:https://www.cnblogs.com/tclan126/p/8485649.html
Copyright © 2011-2022 走看看