1. 程式人生 > >資訊學奧賽一本通 二叉樹遍歷

資訊學奧賽一本通 二叉樹遍歷

題目是:

【題目描述】

輸入一棵二叉樹的先序和中序遍歷序列,輸出其後序遍歷序列。

【輸入】

共兩行,第一行一個字串,表示樹的先序遍歷,第二行一個字串,表示樹的中序遍歷。樹的結點一律用小寫字母表示。

【輸出】

一行,表示樹的後序遍歷序列。

【輸入樣例】

abdec
dbeac

【輸出樣例】

debca

額,真丟臉啊,這道題從11月7日卡在腦袋裡卡到了現在(mmp硬是沒有看題解);

不過老李講的還是挺好的,打call;

本題利用了先序遍歷的“先根”性質(每輸出的一個值都是當先dfs時間戳的節點的值),且序列中的第一個元素一定是根節點;——性質1;

中序遍歷則利用了“左左右右”(左邊的是左兒子,右邊是右兒子);——性質2;

兩者相結合:

我們就可以用先序遍歷的根節點,去找這個根節點在中序遍歷的位置,那麼利用性質2,去找它的左兒子和右兒子的區間分別在哪裡,確定了左兒子和右兒子的區間後,這兩個區間內一定又會有一個“當爸爸的父親節點“,而這個區間裡面的父親節點,一定是先序遍歷中當前節點向後的一個節點(性質1)相當於二分;

下面是程式碼(st是start的縮寫,en是end的縮寫)

1、陣列(在遍歷的時候就輸出)

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
void wans( int st1 , int en1 , int st2 , int en2 ){
	if( st1 <= en1 ){
		int root = s2.find ( s1[st1] , st2 );
		wans ( st1+1 , st1+root-st2 , st2 , root-1 );
		wans ( st1+root-st2+1 , en1 , root+1 , en2 );
		cout<<s1[st1];
	}
}
int main(){
	cin>>s1;
	cin>>s2;
	wans(0 , s1.size()-1 , 0 , s2.size()-1 );
	return 0;
}
2、建樹,先建樹後常規跑後序 dfs;
#include<bits/stdc++.h>
using namespace std;
typedef struct node;
typedef node *tree;
struct node{
	char data;
	tree l,r;
};
tree root;
string s1,s2;
void build( int st1 , int en1 , int st2 , int en2 , tree &bt ){
	bt=new node;
	bt->data = s1[st1];
	if( st1 <= en1 ){
		int x = s2.find( s1[st1] , st2 );
		build( st1+1 , st1+x-st2 , st2 , x-1 , bt->l);
		build( st1+x-st2+1 , en1 , x+1 , en2 , bt->r);
	}
	else
	    bt = NULL;
}
void visit( tree bt ){
	if( bt ){
		visit( bt->l );
		visit( bt->r );
		cout<<bt -> data;
	}
}
int main(){
	cin>>s1;
	cin>>s2;
	build( 0 , s1.size()-1 , 0 , s2.size()-1 , root );
	visit(root);
	return 0;
}
感覺lqx和hy同學學得很快,加油!