淺談二叉樹遍歷的棧方法

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

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結構體),咱們便可以模擬棧的實現,固然,本文主要是談二叉樹的遍歷,至於棧的實現嗎,讀者本身去查嗎!!!spa

  一樣,咱們採用中序遍歷類舉例:指針

先敬上代碼:code

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);
        }
    }
    
}

咱們一一個簡單的二叉樹爲例:blog

image

下面是棧操做過程:遞歸

image

其操做步驟能夠簡介爲以下:get

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

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

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

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

重複。

相關文章
相關標籤/搜索