淺談二叉樹遍歷的棧方法


  眾多周知,對於二叉樹的遍歷, 一種比較容易理解以及編寫的方式就是遞歸的方式了,下面針對二叉樹遍歷的中序遍歷做一個簡單的分析:

void travelTree(BiTree T, int deep){

    if (T->lchild != NULL)
        travelTree(T->lchild, ++deep);
    for (int x = 0; x < deep; x++)
    {
        printf("--");
    }
    printf("%c\n", T->data);
    if (T->rchild != NULL)
        travelTree(T->rchild, deep);
}

俺們也知道,遞歸算法的思想有其值的我們學習之處,但是,不過否認,遞歸的代價也是蠻高的,這得從遞歸的原理來分析,這里做一下簡單的敘述:

大家都知道遞歸的實現是通過調用函數本身,函數調用的時候,每次調用時要做地址保存,參數傳遞等,這是通過一個遞歸工作棧實現的。具體是每次調用函數本身要保存的內容包括:局部變量、形參、調用函數地址、返回值。那么,如果遞歸調用N次,就要分配N*局部變量、N*形參、N*調用函數地址、N*返回值。這勢必是影響效率的。

  那么,作為遞歸的一種替代方式,棧的實現,就成為了一種不錯的選擇:下面我就簡單的敘述一下,如何在實現二叉樹的遍歷中來運用棧的思想:

  其實嘛,說到底,遞歸的底層(系統級)實現也是使用棧的,如上所說,故遞歸的棧替換依舊不足為奇了,棧是一種先進后出結構的容器,通過簡單的數據結構(j結構體),我們即可以模擬棧的實現,當然,本文主要是談二叉樹的遍歷,至於棧的實現嗎,讀者自己去查嗎!!!

  同樣,我們采用中序遍歷類舉例:

先敬上代碼:

voidt InOrderTraverse(BiTree T, int(*Visit)(TElemType e)){
    InitStake(S);
    Push(S, T);
    while (!StackEmpty(S))
    {
        while (GetTop(S,P)&&p)
            Push(S, p->lchild);
        Pop(S, p);   //空指針null退棧 有左孩子時,在沿着左孩子方向遍歷的時候,會把一個
            //null push進棧沒左孩子的時候,上一次循環就必定會push進一個null  兩種情況互斥 
        if (!StackEmpty(S))
        {
            Pop(S, p);   
            if (!Visit(p->data))
            {
                return error;
            }
            Push(S, p->rchild);
        }
    }
    
}

我們一一個簡單的二叉樹為例:

image

下面是棧操作過程:

image

其操作步驟可以簡介為如下:

1:沿着p左孩子方向深度遍歷值沒有左孩子的節並按循序入棧。(前提:有左孩子)  最對會帶一個空指針

      去棧頂的空指針(此時棧頂絕對有一個空指針)

2:操作棧頂節點節點(訪問)

3:p指向此節點的右節點(不詢問)   即可能為空

重復。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM