1. 程式人生 > 其它 >二叉樹的先序遍歷、中序遍歷、後序遍歷-C語言描述

二叉樹的先序遍歷、中序遍歷、後序遍歷-C語言描述

目錄

什麼是先序、中序、後序

  • 先序遍歷先訪問根結點,再先序遍歷左子樹,再先序遍歷右子樹
  • 中序先中序遍歷左子樹,再訪問根節點,再遍歷右子樹
  • 後序先遍歷左子樹,再遍歷右子樹,再訪問根節點

各順序的實質(竅門)

各順序遍歷走的路徑相同,從根節點從左邊開始繞著二叉樹走,每個結點會遇到3次,先序就是第一次遇到結點就輸出一次(或者其他操作),中序就是第二次碰到時輸出,後序就是第三次碰到時輸出。

遞迴實現

先序遍歷的遞迴遍歷演算法

void PreOrderTraversal(BinTree BT)
{
	if(BT)
	{
		printf("%d",BT->Date);
		PreOrderTraversal(BT->Left);
  		PreOrderTraversal(BT->Right);
	}
}

中序遍歷

void InOrderTraversal(Bintree BT)
{
	if(BT){
	InOrderTraversal(BT->Left);
	printf("%d",BT->Date);
	InorderTraversal(BT->Right);
	}
}

後序遍歷

void PostOrderTraversal(BinTree BT)
{
	if(BT)
	{
		PreOrderTraversal(BT->Left);
  		PreOrderTraversal(BT->Right);
		printf("%d",BT->Date);
	}
}

堆疊迴圈實現

先序遍歷的非遞迴迴圈演算法

void PreOrderTraversal(BinTree BT)
{
	BinTree T=BT;
	Stack S=CreatStack(Maxsize);//建立並初始化堆疊
	while(T || !IsEmpty(S)){
		while(T){    //一直向左並將沿途結點壓入堆疊
			printf("%d",T->Date);//第一次遇到時就列印
			push(S,T);
			T=T->Left;
		}
		if(!IsEmpty(S)){
			T=pop(S);//結點彈出堆疊
			T=T->Right;//轉向右結點
		}
	}
}

中序遍歷的非遞迴迴圈演算法

  • 遇到一個節點把他壓棧,並去遍歷它的左子樹
  • 當左子樹遍歷完成,彈出棧頂節點,並訪問它
  • 然後根據其右指標中序遍歷其右子樹
void InOrdertraversal(BinTree BT)
{
	BinTree T=BT;
	Stack S=CreatStack(Maxsize);//建立並初始化棧
	while(T || !IsEmpty(S)){
		while(T){//中序遍歷第二次碰到時再列印
			push(S,T);
			T=T->Left;
		}
		if(!IsEmpty(S)){
			T=pop(S);
			printf("%d",T->Date);
			T=T->Right;
			/*訪問最左邊的葉子結點時,列印了它本身,
			再將它的右子樹(NULL)賦值給T,經過判斷,
			就會彈出葉子結點的父元素。如果理解不了就記住。*/
		}
	}
}

後序遍歷


從根節點開始,向左繞圈,第3次經過的節點並輸出就是後序遍歷
如果逆著來看,從右邊開始繞圈,第1次經過的結點剛好是從左邊繞圈第3次經過的結點
只不過方向剛好相反,我們可以把前序遍歷的Left與Right交換位置,然後再用另一個棧記錄每次遇到的結點
最後依次取出來

void PostOrderTraversal(BinTree BT)
{
	BinTree T=BT;
	Stack S=CreatStack(Maxsize);//建立並初始化堆疊
	Stack R=CreatStack(Maxsize);
	while(T || !IsEmpty(S)){
		while(T){    //一直向右並將沿途結點壓入堆疊
			push(R,T);
			push(S,T);
			T=T->Right;
		}
		if(!IsEmpty(S)){
			T=pop(S);//結點彈出堆疊
			T=T->Left;
		}
	}
	while(!IsEmpty(R)){//R彈棧
		T=pop(R);
		printf("%d",T->Date);
	}
}