二叉樹先序遍歷、中序遍歷、後序遍歷的遞迴演算法與非遞迴演算法
阿新 • • 發佈:2018-12-05
首先是二叉樹資料結構的定義:
typedef struct TNode *Position;
typedef Position BinTree; /* 二叉樹型別 */
struct TNode{ /* 樹結點定義 */
int Data; /* 結點資料 */
BinTree Left; /* 指向左子樹 */
BinTree Right; /* 指向右子樹 */
};
遞迴演算法
/*****************遞迴演算法******************/ /*****先序遍歷*****/ void PreOrderTraversal(BinTree BT) { if( BT ){ printf("%d ",BT->Data); //先訪問根節點 PreOrderTraversal(BT->Left); //再訪問左子樹 PreOrderTraversal(BT->Right); //最後訪問右子樹 } } /*****中序遍歷*****/ void InOrderTraversal(BinTree BT) { if( BT ){ InOrderTraversal(BT->Left); printf("%d ",BT->Data); InOrderTraversal(BT->Right); } } /*****後序遍歷*****/ void PostOrderTraversal(BinTree BT) { if( BT ){ PostOrderTraversal(BT->Left); PostOrderTraversal(BT->Right); printf("%d ",BT->Data); } }
非遞迴演算法
/*****************非遞迴演算法******************/ /*****先序遍歷*****/ void PreOrderTraversal_(BinTree BT) { BinTree T = BT; Stack S = CreatStack(MaxSize); /*建立並初始化堆疊S*/ while( T || !IsEmpty(S) ){ while( T ){ /*一直向左並將沿途結點壓入堆疊,直到左兒子不存在*/ printf("%5d ",T->Data); /*訪問(列印)結點*/ 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); /*建立並初始化堆疊S*/ while( T || !IsEmpty(S) ){ while( T ){ /*一直向左並將沿途結點壓入堆疊,直到左兒子不存在*/ Push(S,T); T = T->Left; } if( !IsEmpty(S) ){ T = Pop(S); /*結點彈出堆疊*/ printf("%5d ",T->Data); /*訪問(列印)結點*/ T = T->Right; /*轉向右子樹*/ } } } /*****後序遍歷*****/ /*1 給數的結點增加一個訪問次數(visit)屬性 遍歷左子樹,依次入棧 到底後出棧一個元素,判斷訪問次數是否為2 若不是,則訪問次數為1,訪問次數+1,再次入棧,T指向右子樹(訪問右子樹),進入下次迴圈 若是,則輸出,T指向空(左右子樹都訪問了),進入下次迴圈 */ void PostOrderTraversal_1(BinTree BT) { BinTree T,BT; Stack S = CreatStack(Maxsize); while( T || !IsEmpty(s)) { while(T){ T->visit++;//visit初值為0 Push(S,T); T = T->Left; } if( !isEmpty(S) ){ T = Pop(S);//出棧判斷 if(T->visit==2){ printf("%5d",T->data); T = NULL; } else{ T->visit++; Push(S,T);//訪問次數不等於2,二次入棧 T = T->Right; } } } } /*2 先序的訪問順序是root, left, right 假設將先序左右對調, 則順序變成root, right, left,暫定稱之為“反序”。 後序遍歷的訪問順序為left, right,root , 剛好是“反序”結果的逆向輸出. */ void PostOrderTraversal_2( BinTree BT ) { BinTree T,BT; Stack S = CreatStack( MaxSize ); /*建立並初始化堆疊S*/ Stack Q = CreatStack( MaxSize ); /*建立並初始化堆疊Q,用於輸出反向*/ while( T || !IsEmpty(S) ){ while(T){ /*一直向右並將沿途結點壓入堆疊*/ Push(S,T); Push(Q,T);/*將先序遍歷到的結點壓棧,用於反向*/ T = T->Right; /*轉向右子樹*/ } if(!IsEmpty(S)){ T = Pop(S); T = T->Left; /*轉向左子樹*/ } } while( !IsEmpty(Q) ){ T = Pop(Q); printf("%5d ", T->Data); } } /*3 後序遍歷是先訪問左,再訪問右,最後訪問根 當且僅當右子樹為空或者右子樹被訪問過後, 才會訪問根節點,因此使用輔助指標r來記錄最近訪問過的節點 */ void PostOrderTraversal_3(BinTree BT){ BinTree T = BT; BinTree r = NULL; Stack S = CreatStack(MaxSize); while( T || !isEmpty(S) ){ if( T ){ //遍歷到最左邊 Push(S, T); T = T->left; } else{ GetTop(S,T); //讀取棧頂節點 if(T->right && T->right != r) T = T->right; else{ T = Pop(S); printf("%5d ", T->data); r = T; //記錄最近訪問的節點 T = NULL; //節點訪問完後重置T指標 } } } }