二叉樹的非遞迴遍歷(遞迴和非遞迴)

2022-02-05 06:13:16 字數 2792 閱讀 5527

二 叉樹是一種非常重要的資料結構,很多其它資料結構都是基於二叉樹的基礎演變而來的。對於二叉樹,有前序、中序以及後序三種遍歷方法。因為樹的定義本身就是 遞迴定義,因此採用遞迴的方法去實現樹的三種遍歷不僅容易理解而且**很簡潔。而對於樹的遍歷若採用非遞迴的方法,就要採用棧去模擬實現。在三種遍歷中, 前序和中序遍歷的非遞迴演算法都很容易實現,非遞迴後序遍歷實現起來相對來說要難一點。

一.前序遍歷

前序遍歷按照「根結點-左孩子-右孩子」的順序進行訪問。

1.遞迴實現

[cpp]view plain

copy

void

pre_order(btree *root)    

}    

2.非遞迴實現

根據前序遍歷訪問的順序,優先訪問根結點,然後再分別訪問左孩子和右孩子。即對於任一結點,其可看做是根結點,因此可以直接訪問,訪問完之後,若其左孩子不為空,按相同規則訪問它的左子樹;當訪問其左子樹時,再訪問它的右子樹。因此其處理過程如下:

對於任一結點p:

1)訪問結點p,並將結點p入棧;

2)判斷結點p的左孩子是否為空,若為空,則取棧頂結點並進行出棧操作,並將棧頂結點的右孩子置為當前的結點p,迴圈至1);若不為空,則將p的左孩子置為當前的結點p;

3)直到p為null並且棧為空,則遍歷結束。

[cpp]view plain

copy

//非遞迴前序遍歷 

void

pre_order(btree *root)       

if(!s.empty())   

}  }  

二.中序遍歷

中序遍歷按照「左孩子-根結點-右孩子」的順序進行訪問。

1.遞迴實現

[cpp]view plain

copy

void

in_order(btree* root)    

}   

2.非遞迴實現

根據中序遍歷的順序,對於任一結點,優先訪問其左孩子,而左孩子結點又可以看做一根結點,然後繼續訪問其左孩子結點,直到遇到左孩子結點為空的結點才進行訪問,然後按相同的規則訪問其右子樹。因此其處理過程如下:

對於任一結點p,

1)若其左孩子不為空,則將p入棧並將p的左孩子置為當前的p,然後對當前結點p再進行相同的處理;

2)若其左孩子為空,則取棧頂元素並進行出棧操作,訪問該棧頂結點,然後將當前的p置為棧頂結點的右孩子;

3)直到p為null並且棧為空則遍歷結束

[cpp]view plain

copy

//非遞迴中序遍歷 

void

in_order(btree *root)       

if(!s.empty())   

}  }  

三.後序遍歷

後序遍歷按照「左孩子-右孩子-根結點」的順序進行訪問。

1.遞迴實現

[cpp]view plain

copy

void

post_order(btree* root)    

}      

2.非遞迴實現

後序遍歷的非遞迴實現是三種遍歷方式中最難的一種。因為在後序遍歷中,要保證左孩子和右孩子都已被訪問並且左孩子在右孩子前訪問才能訪問根結點,這就為流程的控制帶來了難題。下面介紹兩種思路。

第一種思路:對於任一結點p,將其入棧,然後沿其左子樹一直往下搜尋,直到搜尋到沒有左孩子的結點,此時該結點出現在棧頂,但是此時不能將其出棧並訪問,

因此其右孩子還為被訪問。所以接下來按照相同的規則對其右子樹進行相同的處理,當訪問完其右孩子時,該結點又出現在棧頂,此時可以將其出棧並訪問。這樣就

保證了正確的訪問順序。可以看出,在這個過程中,每個結點都兩次出現在棧頂,只有在第二次出現在棧頂時,才能訪問它。因此需要多設定乙個變數標識該結點是

否是第一次出現在棧頂。

方法:要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點p,先將其入棧。如果p不存在左孩子和右孩子,則可以直接訪問它;或者p存在左孩子

或者右孩子,但是其左孩子和右孩子都已被訪問過了,則同樣可以直接訪問該結點。若非上述兩種情況,則將p的右孩子和左孩子依次入棧,這樣就保證了每次取棧

頂元素的時候,左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。

[cpp]view plain

copy

//非遞迴後序遍歷

void

post_order(btree* root)       

else

}      

}  四、層次遍歷

//採用stl中的queue處理

[cpp]view plain

copy

#include 

void

layerorder(btree *tree)  

/樹的深度

int treedepth(btree* root)

//總共節點

int totalnode(btree* root)

return ntotal;

}

//葉子節點

int leafnode(btree* root)

leafnode(root->lchild);

leafnode(root->rchild);

} return nleaf;

}

二叉樹遍歷(遞迴 非遞迴)

二叉樹以及對二叉樹的三種遍歷 先根,中根,後根 的遞迴遍歷演算法實現,以及先根遍歷的非遞迴實現。node public class node public node left public node right public object value 遍歷訪問操作介面 public inte ce ...

二叉樹遍歷(遞迴和非遞迴)

二叉樹的中序遍歷 二叉樹的後序遍歷 測試二叉樹的節點定義如下 節點 二叉樹的前序遍歷順序為 根左右。如下圖所示,前序遍歷順序為 1245367。遞迴 public static void preorder treenode root system.out.print root.val preorde...

二叉樹遞迴遍歷和非遞迴遍歷

用遞迴和非遞迴實現二叉樹的前序遍歷 中序遍歷和後序遍歷並列印出相應結果。private class treenode 在遞迴呼叫時候系統自動給我們建立棧來儲存資料,而使用非遞迴時候需要我們自己實現棧來儲存資料。遞迴實現前序遍歷public void preorder treenode root sy...