1. 程式人生 > >二叉樹非遞迴遍歷的通用演算法

二叉樹非遞迴遍歷的通用演算法

二叉樹的3中遍歷策略,關鍵在於處理節點的時機不同:前序遍歷是遇到節點時處理,中序是處理完左節點後再處理,而後序是在處理完左右節點後再處理。

使用非遞迴方法實現時,除了記錄當前的節點的訪問棧,還需要記錄當前節點的狀態。對於每一個節點,我們用0來表示尚未處理左右子節點,1表示僅僅處理完畢左節點,2表示左右節點都處理完畢。那麼,前序,中序,後序遍歷的唯一不同,無非是對節點處理的時機不同而已。


const int MAX=20;
typedef struct Node
{
	char data;
	struct Node*lchild;
	struct Node*rchild;
}BiTreeNode;

const int STATE_NONE=0;//尚未處理任何一個節點 
const int STATE_LEFT_DONE=1;//處理完左節點 
const int STATE_LEFT_RIGHT_DONE=2;//左右節點都已經處理完 


/*
 演算法說明:初始時放入根節點,將其標記為左右節點尚未處理的狀態 
 每個迴圈,從棧中取出一個節點和其狀態,根據其當前狀態轉移到下一個狀態
(很顯然,你可以從狀態轉換機的角度解讀這個演算法)。 
 狀態轉換規則: STATE_NONE-->STATE_LEFT_DONE-->STATE_LEFT_RIGTH_DONE-->彈出棧 
 伴隨狀態的變化,還需要相應的操作,如將左右子節點放入棧中,或者將當前節點彈出棧;
 最重要的一點是,噹噹前節點的狀態符合處理狀態的要求時,就會處理該節點。
 */
void travese(BiTreeNode*T,int when)
{
	if(when!=STATE_NONE||when!=STATE_LEFT_DONE||when!=STATE_LEFT_RIGHT_DONE)
	 {
	 	printf("狀態輸入有誤,請重新輸入");
	 	exit(1);
	 }
	BiTreeNode*Stack[MAX]; //儲存節點的棧
	int stackState[MAX];   //儲存節點狀態的棧 
	int top=0;
	Stack[++top]=T;			//根節點入棧
	stackState[top]=STATE_NONE;	//根節點狀態入棧 
	
	while(top>0)
	{
		BiTreeNode *p=Stack[top];
		int state=stackState[top];
		
		if(state==when)    //當前狀態可以處理節點
			printf("%2c",p->data);
		
		//3中狀態之間的轉換 
		switch(state)
		{
			case STATE_NONE:
								stackState[top]=STATE_LEFT_DONE;
								if(p->lchild)
								{
									Stack[++top]=p->lchild;
									stackState[top]=STATE_NONE; 
								}
								break;
			case STATE_LEFT_DONE:
								stackState[top]=STATE_LEFT_RIGHT_DONE;
								if(p->rchild)
								{
									Stack[++top]=p->rchild;
									stackState[top]=STATE_NONE; 
								}
								break;
			case STATE_LEFT_RIGHT_DONE:
									top--;
									break;																				
		}
			
	} 
	
}

原文連結:https://www.jianshu.com/p/8359c1369066