1. 程式人生 > >Tree-UVA 548

Tree-UVA 548

als 得出 open += 方法 basic 利用 getline -i

1.題目描述:點擊鏈接

2.問題分析:

題目已經給出了某二叉樹經過中序遍歷和後序遍歷得到的節點順序,要求通過這些節點的值以及順序,找到原有的二叉樹以及到根節點最近的葉子節點。

我認為最主要的是找到後序遍歷和中序遍歷得到的節點順序有什麽規律

我們知道,中序遍歷首先遍歷左子樹,然後訪問根結點,最後遍歷右子樹,而後序遍歷首先遍歷左子樹,然後遍歷右子樹,最後訪問根節點。所以由此我們不難得出以下幾個結論:

(1)中序遍歷的左子樹和右子樹分布於根節點的兩側。

(2)後序遍歷最後一個值一定是根節點,

(3)這兩種遍歷方法都是可以使用遞歸,任何一個左子樹和右子樹都可以看成另外一顆完整的二叉樹

3.算法步驟:

(1)通過後序遍歷給的值找到根節點,在利用找到的根節點在中序遍歷給的值中找到左子樹和右子樹

(2)通過遞歸,還原出完整的二叉樹

(3)使用DFS找到路徑最短的路線

4.ac代碼:

 1 #include<iostream>
 2 #include<string>
 3 #include<stdlib.h>
 4 #include<sstream>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxn=10000+10;
 8 int in_order[maxn],post_order[maxn],lch[maxn],rch[maxn];
 9 int n;
10 bool read_list(int *a){ 11 string line; 12 if(!getline(cin,line))return false; 13 stringstream ss(line); 14 n=0; 15 int x; 16 while(ss>>x)a[n++]=x; 17 return n>0; 18 } 19 int build(int L1,int R1,int L2,int R2){//建二叉樹,返回樹根 20 if(L1>R1)return 0;//空樹 21 int root=post_order[R2];
22 int p=L1; 23 while(in_order[p]!=root)p++; 24 int cnt=p-L1;//左子樹的節點個數 25 cout<<"L1,p-1,L2,L2+cnt-1"<<endl; 26 cout<<L1<<" "<<p-1<<" "<<L2<<" "<<L2+cnt-1<<endl; 27 28 lch[root]=build(L1,p-1,L2,L2+cnt-1); 29 30 cout<<"lch["<<root<<"]="<<lch[root]<<endl; 31 cout<<"p+1,R1,L2+cnt,R2-1"<<endl; 32 cout<<p+1<<" "<<R1<<" "<<L2+cnt<<" "<<R2-1<<endl; 33 34 rch[root]=build(p+1,R1,L2+cnt,R2-1); 35 36 cout<<"rch["<<root<<"]="<<rch[root]<<endl; 37 return root; 38 } 39 int best,best_sum; 40 void dfs(int u,int sum){ 41 sum+=u; 42 if(!lch[u]&&!rch[u]){ 43 if(sum<best_sum||(sum==best_sum&&u<best)){best=u;best_sum=sum;} 44 } 45 if(lch[u])dfs(lch[u],sum); 46 if(rch[u])dfs(rch[u],sum); 47 } 48 int main(){ 49 //freopen("in.txt","r",stdin); 50 while(read_list(in_order)){ 51 read_list(post_order); 52 build(0,n-1,0,n-1); 53 best_sum=1000000000; 54 dfs(post_order[n-1],0); 55 cout<<best<<"\n"; 56 } 57 return 0; 58 }

Tree-UVA 548