什么是先序、中序、后序
- 先序遍歷先訪問根結點,再先序遍歷左子樹,再先序遍歷右子樹
- 中序先中序遍歷左子樹,再訪問根節點,再遍歷右子樹
- 后序先遍歷左子樹,再遍歷右子樹,再訪問根節點
各順序的實質(竅門)
各順序遍歷走的路徑相同,從根節點從左邊開始繞着二叉樹走,每個結點會遇到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);
}
}
