二叉樹的遍歷(遞迴與非遞迴)
阿新 • • 發佈:2019-01-20
本文討論二叉樹的常見遍歷方式的程式碼(Java)實現,包括前序(preorder)、中序(inorder)、後序(postorder)、層序(level order),進一步考慮遞迴和非遞迴的實現方式。
遞迴的實現方法相對簡單,但由於遞迴的執行方式每次都會產生一個新的方法呼叫棧,如果遞迴層級較深,會造成較大的記憶體開銷,相比之下,非遞迴的方式則可以避免這個問題。遞迴遍歷容易實現,非遞迴則沒那麼簡單,非遞迴呼叫本質上是通過維護一個棧,模擬遞迴呼叫的方法呼叫棧的行為。
在此之前,先簡單定義節點的資料結構:
二叉樹節點最多隻有兩個兒子,並儲存一個節點的值,為了實驗的方便,假定它為 int。同時,我們直接使用 Java 的 System.out.print 方法來輸出節點值,以顯示遍歷結果。
1 2 3 4 5 6 7 8 9 |
|
前序遍歷
遞迴實現
遞迴實現很簡單,在每次訪問到某個節點時,先輸出節點值,然後再依次遞迴的對左兒子、右兒子呼叫遍歷的方法。程式碼如下
1 |
|
非遞迴調實現
方法 1
1 2 3 4 5 6 7 8 9 10 11 12 |
|
-
描述
維護一個棧,將根節點壓入棧中。此後,每次從棧中讀出棧頂的節點,作為對節點的訪問,然後將該節點的兒子節點按照先右後左的順序,壓入棧中,實現遞迴模擬。
-
分析
這個棧的遞迴策略不具備很好的擴充套件性,其他的遍歷方式無法使用這種策略。實際上,它並不是對程式呼叫棧的模擬,而是針對先序遍歷的特殊實現:先序遍歷先對當前節點做出訪問後,然後遞迴的呼叫對兒子節點的遍歷,不需要在對兒子節點遍歷結束後再回過頭來處理當前節點。於是模擬的遞迴中也不需要儲存之前的呼叫棧資訊,只需要類似的生成一個未來的兒子節點的訪問計劃即可。
方法 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|