1. 程式人生 > >資料結構——樹——二叉樹遍歷

資料結構——樹——二叉樹遍歷

遍歷是對樹的一種最基本的運算,所謂遍歷二叉樹,就是按一定的規則和順序走遍二叉樹的所有結點,使每一個結點都被訪問一次,而且只被訪問一次。由於二叉樹是非線性結構,因此,樹的遍歷實質上是將二叉樹的各個結點轉換成為一個線性序列來表示。
設L、D、R分別表示遍歷左子樹、訪問根結點和遍歷右子樹, 則對一棵二叉樹的遍歷有三種情況:DLR(稱為先根次序遍歷),LDR(稱為中根次序遍歷),LRD (稱為後根次序遍歷)。
二叉樹的遍歷
在這裡插入圖片描述

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 );
        /* 此處假設對BT結點的訪問就是列印資料 */
        printf("%d ", BT->Data); /* 假設資料為整型 */
        InorderTraversal
( BT->Right ); } }

在這裡插入圖片描述

void PostorderTraversal( BinTree BT )
{
    if( BT ) {
        PostorderTraversal( BT->Left );
        PostorderTraversal( BT->Right );
        printf("%d ", BT->Data);
    }
}

在這裡插入圖片描述

void LevelorderTraversal ( BinTree BT )
{ 
    Queue Q; 
    BinTree T;
    if
( !BT ) return; /* 若是空樹則直接返回 */ Q = CreatQueue(); /* 建立空佇列Q */ AddQ( Q, BT ); while ( !IsEmpty(Q) ) { T = DeleteQ( Q ); printf("%d ", T->Data); /* 訪問取出佇列的結點 */ if ( T->Left ) AddQ( Q, T->Left ); if ( T->Right ) AddQ( Q, T->Right ); } }

層序基本過程:先根結點入隊,然後:

  1. 從佇列中取出一個元素;
  2. 訪問該元素所指結點;
  3. 若該元素所指結點的左、右孩子結點非空, 則將其左、右孩子的指標順序入隊。

中序遍歷非遞迴遍歷演算法
遇到一個結點,就把它壓棧,並去遍歷它的左子樹;
當左子樹遍歷結束後,從棧頂彈出這個結點並訪問它;
然後按其右指標再去中序遍歷該結點的右子樹。

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; /*轉向右子樹*/
        }
    }
}

先序遍歷的非遞迴遍歷演算法

void PreOrderTraversal( BinTree BT )
{
    BinTree T BT;
    Stack S = CreatStack( MaxSize ); /*建立並初始化堆疊S*/
    while( T || !IsEmpty(S) )
    {
        while(T)    /*一直向左並將沿途結點壓入堆疊*/
        {
            Push(S,T);
            printf(%5d”, T->Data); /*(訪問)列印結點*/
            T = T->Left;
        }
        if(!IsEmpty(S))
        {
            T = Pop(S); /*結點彈出堆疊*/
            T = T->Right; /*轉向右子樹*/
        }
    }
}

後序遍歷非遞迴遍歷演算法

void PostOrderTraversal( BinTree BT )
{
    BinTree T BT,t;
    Stack S = CreatStack( MaxSize ); /*建立並初始化堆疊S*/
    while( T || !IsEmpty(S) )
    {
        while(T)    /*一直向左並將沿途結點壓入堆疊*/
        {
            Push(S,T);
            T = T->Left;
        }
        if(!IsEmpty(S))
        {
            T=S.top();
            if(T->Right&&T->Right!=t){//右子樹存在且未被訪問
                T=T->Right;
            }
            else {
            T = Pop(S); /*結點彈出堆疊*/
            printf(%5d”, T->Data); /*(訪問)列印結點*/
            t=T;
            T = NULL; /*重置*/
            }
        }
    }
}

在這裡插入圖片描述 先序輸出葉結點

在這裡插入圖片描述求二叉樹高度
類似的:
計算給定二叉樹T的寬度
在這裡插入圖片描述字首表示式

注意:由兩種遍歷序列確定二叉樹 必須要有中序序列才行

在這裡插入圖片描述實現程式碼

根據後序和中序遍歷輸出先序遍歷

以下為習題:

例題:二叉樹的遍歷

練習:樹的同構

練習:判斷一顆二叉樹是否是另一顆樹的子樹