一個函數實現二叉樹非遞歸前中後序遍歷(感謝浙大數據結構陳越、何欽銘老師)

在看慕課上面浙大數據結構時很巧合的想到的寫法,感謝浙大陳越、何欽銘老師:

一個二叉樹的遍歷分前中後序的遍歷,這裏前中後序是如何遍歷的就不多說了。

先給大家看這張圖:


按照讀出來的順序是前序遍歷,正好是第一次經過該節點

按照讀出來的順序是中序遍歷,正好是第二次經過該節點

按照讀出來的順序是後序遍歷,正好是第三次經過該節點

那麼我們的出來一個結論:按照第1、2、3次經過該節點讀出來的順序就是二叉樹的  前、中、後 遍歷了,且每個節點被經過了3次

那麼我們可以用一個棧存放這些路徑上的節點,另一個棧存放對應位置的節點是第幾次經過,那麼不就能實現前中後序的非遞歸的遍歷了嘛:

typedef struct Tree
{
    char data;
    struct Tree *lchild;
    struct Tree *rchild;
} Tree, *Index_Tree;

/**
對於一個二叉樹,整個遞歸遍歷過程每個節點經過了3次;
那麼實現非遞歸遍歷時可以:
   申請一個棧A用來存貯節點,
   另外申請一個棧B用來存貯對應節點位置經過了幾次

先把根節點入棧A,並把1入棧B


A棧不爲空就一直循環:
當第一次訪問一個節點時,先訪問它的左子樹:
    if  爲空
        B棧頂元素置爲2,                      因爲左子樹爲空,說明再次訪問到了當前節點;
    else
        左子樹入棧A,並1入棧B                 因爲第一次訪問到左子樹


當第二次訪問到一個節點時,訪問它的右子樹;
    if 爲空
        B棧頂元素置3                          因爲右子樹爲空,說明又返回到了當前節點;
    else
        將右子樹入棧A,並1入棧B               因爲右子樹第一次被訪問到

當第三次訪問到一個節點時
    讓它出棧, 即A、B棧頂元素出棧
    並且    在上面的基礎上,B棧頂元素+1      因爲又再次訪問到該元素了
**/

void Stack_Pri_Order(Index_Tree T, int x)  ///x爲1時前序遍歷,x爲2時中序遍歷, x爲3時後序遍歷
{
    if(!T)   ///二叉樹不存在返回
        return ;

    Index_Tree p;
    stack<Index_Tree> node;
    stack<int> flag;

    node.push(T);
    flag.push(1);
    while(!node.empty())
    {
        if(flag.top() == 1)   ///第一次訪問該節點
        {
            p = node.top();

            if(x == 1)
                printf("%c", p->data);
            if(!p->lchild)
            {
                flag.pop();
                flag.push(2);
            }
            else
            {
                node.push(p->lchild);
                flag.push(1);
            }
        }
        else if(flag.top() == 2)     ///第二次訪問該節點
        {
            p = node.top();

            if(x == 2)
                printf("%c", p->data);
            if(!p->rchild)
            {
                flag.pop();
                flag.push(3);
            }
            else
            {
                node.push(p->rchild);
                flag.push(1);
            }
        }
        else                           ///第三次訪問該節點
        {
            p = node.top();
            if(x == 3)
                printf("%c", p->data);
            node.pop();
            flag.pop();

            if(!flag.empty())        ///如果根節點沒有出來,就要讓現在的棧頂元素+1
            {
                int  a = flag.top();
                flag.pop();
                flag.push(++a);
            }
        }
    }

    return ;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章