1. 程式人生 > >二叉樹的非遞迴遍歷(先序、中序、後序和層序遍歷)

二叉樹的非遞迴遍歷(先序、中序、後序和層序遍歷)

[前文]

二叉樹的非遞迴遍歷有 先序遍歷、中序遍歷 後續遍歷 和 層序遍歷。

非遞迴演算法實現的基本思路:使用堆疊。而層序遍歷的實現:使用佇列。

如下圖所示的二叉樹:

    

前序遍歷順序為:ABCDE  (先訪問根節點,然後先序遍歷其左子樹,最後先序遍歷其右子樹)

中序遍歷順序為:CBDAE  (先中序遍歷其左子樹,然後訪問很節點,最後中序遍歷其右子樹)

後續遍歷順序為:CDBEA  (先後序遍歷其左子樹,然後後續其右子樹,最後訪問根節點)

層序遍歷順序為:ABECD   (由上至下、從左到右遍歷二叉樹)

 

[準備]

  1. 堆疊的儲存結構和相關操作(具體見: 堆疊的定義與操作——順序儲存和鏈式儲存

  2. 佇列的儲存結構和相關操作(具體見:佇列的定義與操作——順序儲存和鏈式儲存

  3. 建立二叉樹。

 1 typedef struct TreeNode *BinTree;
 2 struct TreeNode {
 3     char Data;
 4     BinTree Left;
 5     BinTree Right;
 6 };
 7 
 8 BinTree CreateBinTree(BinTree T)
 9 {
10     char c;
11     scanf("
%c", &c); 12 if ( c != '#' ) { 13 T = (BinTree)malloc(sizeof(struct TreeNode)); 14 T->Data = c; 15 T->Left = CreateBinTree(T->Left); 16 T->Right = CreateBinTree(T->Right); 17 } 18 else { 19 T = NULL; 20 } 21 return T; 22 }

[實現]  

  1. 先序遍歷

 1 void PreOrderTraverse(BinTree BT)
 2 {
 3     BinTree T = BT;
 4     Stack S = CreateStack();    /* 建立並初始化堆疊  */
 5     while ( T || !IsEmpty(S) ) {
 6         while ( T ) {         /* 一直向左並將沿途節點壓入棧底  */
 7             printf("%c ", T->Data);    /* 列印節點資料 */
 8             Push(S, T);
 9             T = T->Left;  
10         }
11         if ( !IsEmpty(S) ) {
12             T = Pop(S);            /* 節點彈出堆疊 */ 
13             T = T->Right;        /* 轉向右子樹 */ 
14         }
15     }
16 }

  2.中序遍歷

 1 void InOrderTraverse(BinTree BT)
 2 {
 3     BinTree T = BT;
 4     Stack S = CreateStack();    /* 建立並初始化堆疊  */
 5     while ( T || !IsEmpty(S) ) {
 6         while ( T ) {         /* 一直向左並將沿途節點壓入棧底  */
 7             Push(S, T);
 8             T = T->Left;  
 9         }
10         if ( !IsEmpty(S) ) {
11             T = Pop(S);            /* 節點彈出堆疊 */ 
12             printf("%c ", T->Data);    /* 列印節點資料 */
13             T = T->Right;        /* 轉向右子樹 */ 
14         }
15     }
16 }

  3. 後序遍歷

struct Node {
    BinTree BT;
    char Tag;
};
typedef struct Node *PtrToNode;

void PostOrderTraverse(BinTree T)
{
    BinTree P = T;
    struct Node *PNode;
    Stack S = CreateStack();
    
    while ( P || !IsEmpty(S) ) {
        // 遍歷左子樹 
        while ( P ) {
            PNode = (struct Node*)malloc(sizeof(struct Node));
            PNode->BT = P;
            PNode->Tag = 'L';    //  第一次被標記 
            Push(S, PNode);
            P = P->Left;
        }
        // 棧不空 並且  棧頂元素 是第二次被標記 
        while ( !IsEmpty(S) && GetTop(S)->Tag == 'R' ) {
            PNode = Pop(S);
            printf("%c ", PNode->BT->Data);
        }
        
        if ( !IsEmpty(S) ) {
            PNode = GetTop(S);
            PNode->Tag = 'R';    // 第二次被標記 
            P = PNode->BT;
            P = P->Right;         // 轉向右子樹 
        }
    }
}

  4. 層序遍歷

 1 void LevelOrderTraverse(BinTree BT)
 2 {
 3     Queue Q;
 4     ElementType T;
 5     
 6     if ( !BT )    return;    // 若是空樹則返回 
 7     
 8     Q = CreateQueue();    // 建立空佇列  
 9     AddQ(Q, BT);
10     while ( !IsEmpty(Q) ) {
11         T = DeleteQ(Q);
12         printf("%c ", T->Data);
13         if ( T->Left )    AddQ(Q, T->Left);
14         if ( T->Right ) AddQ(Q, T->Right);
15     }
16 }