1. 程式人生 > >1020. Tree Traversals (25)

1020. Tree Traversals (25)

btree size 有變 define i+1 pac sizeof con emp

距離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("\nR:"); for(int i=1;i<=n;i++) { printf("%d ",right[i]); } printf("\n"); */ //層次遍歷 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; }

技術分享圖片

1020. Tree Traversals (25)