1. 程式人生 > >二叉樹中序遍歷、後序遍歷和層序遍歷非遞迴實現

二叉樹中序遍歷、後序遍歷和層序遍歷非遞迴實現

一、中序遍歷

訪問順序:左子樹 -> 結點 -> 右子樹

難點在於訪問左子樹後應該怎麼回到結點本身或者其右子樹呢?這裡利用了堆疊來臨時儲存,需要利用上一個結點時可以pop出來(有種撤回鍵的感覺2333)。

void PreOrderTravel(BinTree BT){
	BinTree T = BT;
	stack<BinTree> st;
	while(T || !st.empty()){
		while(T){
			st.push(T);
			T = T->left;
		}
		if(!st.empty()){
			T = st.top();
			st.pop();
			printf("%d\n", T->data);  
			T = T->right;
		}
	}
}

P.S. 知道了中序遍歷的操作,先序遍歷就更簡單啦,只要在每次壓棧之前輸出結點資料就可以了。 

 

二、後序遍歷

訪問順序:左子樹 ->  右子樹 -> 結點

Question:用這個結點訪問其左右子樹並且再回到其本身後,我怎麼判斷它先前有沒有訪問其左右子樹呢(是否輸出結點資料的判斷條件)?用臨時變數儲存已經輸出資料的結點node,如果當前結點的右子樹和node相等的話,則輸出;反之,不輸出。記得每次輸出後都要彈棧。

void PostOrderTravel(BinTree BT){
	BinTree T = BT;
	stack<BinTree> st;
	while(T || !st.empty()){
		while(T){
			st.push(T);
			T = T->left;
		}
		if(!st.empty()){
			T = st.top();
			if( T->right && T->right != Temp){
				T = T->right;
			}else{
				printf("%d\n", T->data);
				Temp = T;
				T = NULL; //輸出過的資料不必再新增到堆裡,因此置NULL
				st.pop();
			}
		}
	}
}

 

一張圖看清先序、中序、後序之間的關係

 

 三、層序遍歷

訪問順序:從上到下,從左到右

如上圖所示,將A結點pop出的時候,A的左右子樹(B、C)都進隊了;根據進隊順序,當B結點pop出的時候,B的左右子樹(D、F)進隊;以此類推。。。所以有了以下程式碼

void LevelOrderTravel(BinTree BT){
	queue<BinTree> q;
	if(BT==NULL)return;
	q.push(BT);
	while(!q.empty()){
		BT=q.front();
		q.pop();
		printf("%d\n", BT->Data);
		if(BT->left)q.push(BT->left);
		if(BT->right)q.push(BT->right);
	}
}