二叉樹的先序遍歷、中序遍歷、後序遍歷-C語言描述
阿新 • • 發佈:2021-07-12
目錄
什麼是先序、中序、後序
- 先序遍歷先訪問根結點,再先序遍歷左子樹,再先序遍歷右子樹
- 中序先中序遍歷左子樹,再訪問根節點,再遍歷右子樹
- 後序先遍歷左子樹,再遍歷右子樹,再訪問根節點
各順序的實質(竅門)
各順序遍歷走的路徑相同,從根節點從左邊開始繞著二叉樹走,每個結點會遇到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);
}
}