二叉樹的遍歷及例題


二叉樹的遍歷及例題

前序遍歷就是根在前,中序是根在根在中,

前序遍歷

根 --> 左 --> 右

中序遍歷

左 --> 根 --> 右

后序遍歷

左 --> 右 --> 根

如圖是一顆二叉樹

前序(根左右),中序(左根右),后序(左右根)

它的前序遍歷結果為: A B D F G H I E C 代表的含義為A( B ( D ( F ,G( H ,I ) ) ,E ) , C )

所以第一個點一定是根節點

它的中序遍歷結果為: F D H G I B E A C

它代表的含義,A(已知它不是葉子節點)在中間說明A的左邊是左兒子,A的右邊是他的右兒子

它的后序遍歷結果為:F H I G D E B C A

解題:

如果有前序和中序或者中序和后序可以得到二叉樹,從而得到后序。

如果有前序和后序無法的得到二叉樹。

1.已知前序、中序遍歷求后序遍歷

例:

​ 前序遍歷:A B G D E C F H

​ 中序遍歷:G B E D A F C H

構建二叉樹的步驟:

1.根據前序遍歷特點,得到根節點A

2.觀察中序遍歷結果: 根節點左邊節點為G B E D,根節點的右邊節點為 F C H。同時,兩段也是左右子樹的中序遍歷的結果。

​ B G D E也是左子樹前序遍歷的結果。 C F H也是右子樹前序遍歷的結果。

3.重復 1 2的步驟,直到找到葉子結點就可以得到最后的二叉樹。

例題:

https://vjudge.net/contest/407936#problem/K

題意:給出中序遍歷和前序遍歷,讓你找到后序遍歷的結果。

#include <iostream>
using namespace std;
const int maxn = 105;  
int pre[maxn],in[maxn],pos[maxn];

int infind(int root,int l,int r){//在中序遍歷中找到當前根節點的位置 
	for(int i=l;i<r;i++){
		if(in[i]==root){
			return i;
		}
	}	
}
int cnt;

void posorder(int prel,int prer,int inl,int inr){
	if(prel==prer) return ;
	int root=infind(pre[prel],inl,inr);//找當前的根的位置 
	int len=root-inl;
	posorder(prel+1,prel+1+len,inl,inl+len);//prel的位置是root的位置,刪去
	posorder(prel+1+len,prer,inl+1+len,inr);//inl+len+1的位置是root的位置,刪去
    //進行完左邊和右邊的遍歷之后,進行賦值。 左右根
	pos[cnt++]=in[root];
	return;
}

int main(){
	int n;
	while(~scanf("%d",&n)){
		cnt=0;
		for(int i=0;i<n;i++) cin>>in[i];
		for(int i=0;i<n;i++) cin>>pre[i];
		posorder(0,n,0,n);
		for(int i=0;i<n;i++) cout<<pos[i]<<' ';
		cout<<endl;
	}
	return 0;
} 
//關鍵代碼:

void posorder(int prel,int prer,int inl,int inr){
	if(prel==prer) return ;
	int root=infind(pre[prel],inl,inr);//找當前的根的位置 
	int len=root-inl;
	posorder(prel+1,prel+1+len,inl,inl+len);
	posorder(prel+1+len,prer,inl+1+len,inr);
	pos[cnt++]=in[root];//相當於輸出操作
	return;
}

//得到前序遍歷的值
pos[cnt++]=in[root];//相當於輸出操作
posorder(prel+1,prel+1+len,inl,inl+len);
posorder(prel+1+len,prer,inl+1+len,inr);

//得到中序遍歷的值
posorder(prel+1,prel+1+len,inl,inl+len);
pos[cnt++]=in[root];//相當於輸出操作
posorder(prel+1+len,prer,inl+1+len,inr);

//得到后序遍歷的值
posorder(prel+1,prel+1+len,inl,inl+len);
pos[cnt++]=in[root];//相當於輸出操作
posorder(prel+1+len,prer,inl+1+len,inr);

例題:

玩轉二叉樹

https://pintia.cn/problem-sets/994805046380707840/problems/994805065406070784

題意:給你中序遍歷和前序遍歷的結果,讓你找到二叉樹的鏡像,然后按層遍歷輸出

#include <iostream>
using namespace std;
int pre[55],in[55],pos[55];
int ans[55][55];//儲存按層遍歷的結果
//第一個存的哪一層,第二個存的是具體的數,
//ans[t][0]存儲的是該層的數字個數。
int find(int t,int l,int r){
	for(int i=l;i<r;i++){
		if(in[i]==t){
			return i;
		}
	}
}

void ceng(int prel,int prer,int inl,int inr,int t){
	if(prel==prer) return ;
	ans[t][++ans[t][0]]=pre[prel];//存入答案。
	int x=find(pre[prel],inl,inr);
	int len=x-inl;
	ceng(prel+len+1,prer,inl+len+1,inr,t+1);//先遍歷右邊,再遍歷左邊
	ceng(prel+1,prel+len+1,inl,inl+len,t+1);
	return;
}

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>in[i];
	for(int i=0;i<n;i++) cin>>pre[i];
	ceng(0,n,0,n,0);
	int x=0;
		int len=0;
	while(ans[x][0]!=0){
	
		for(int i=1;i<=ans[x][0];i++){
			if(len==0){
				printf("%d",ans[x][i]);
			}else{
				printf(" %d",ans[x][i]);
			}
			len++;
			
		}
		x++;
	}
	return 0;
}

2.已知后序、中序遍歷求前序遍歷

后序遍歷是:左右根,所以根在最后,跟前序遍歷相似,把 prel 和 prer 的值改變一下即可。

3.已知前序、后序遍歷求中序遍歷

無法求得!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM