二叉樹非遞迴遍歷的通用演算法
阿新 • • 發佈:2018-11-02
二叉樹的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; } } }