樹的前中後層序遍歷(遞迴與非遞迴方式)

2021-09-01 12:55:12 字數 1845 閱讀 3112

leetcode的第590題與429、589題型類似,都為樹(不一定是二叉樹)的各種形式的遍歷,因此放在一起總結。

對於上圖,要求求出前序遍歷、後序遍歷和層級遍歷的結果。

前序遍歷結果:[1,3,5,6,2,4]

後序遍歷結果:[5,6,3,2,4,1]

層級遍歷結果:

[ [1],

[3,2,4],

[5,6]

]

對於樹我們一般有兩種策略:

深度優先搜尋(dfs):從乙個根節點開始,一直到達某個葉子節點,然後回到根節點到達另乙個分支的葉子節點。根據根節點、左節點和右節點之間的相對順序,dfs策略可以進一步區分為前序、中序和後序。

對於第一題求前序遍歷,我們可以使用遞迴或者迴圈來完成,實際上這三道題都是如此。我們先看看遞迴版本:

public

class

solution

private

void

preordercore

(node root)

}

前序遍歷就是先將根節點放入結果列表中,然後再將左右子節點放入。遞迴的解法較為簡單,下面看看迴圈的解法:

public

class

solution2

}return res;

}}

在遞迴中我們使用棧來儲存接下來要訪問的節點。首先我們將根節點壓入棧,棧中元素為[1],然後我們將它彈出至結果列表並把它的子節點翻轉並放入棧,此時棧中元素為[4, 2, 3];由於棧頂元素為3,因此將3彈出至結果列表並把它的子節點翻轉並放入棧,此時棧中元素為[4, 2, 6, 5];棧頂元素為5,因此將5彈出至結果列表,5沒有子節點,再把6彈出至結果列表。如此反覆,我們便可以通過這種方式得到前序遍歷的結果列表[1, 3, 5, 6, 2, 4]

求後序遍歷與這題異曲同工,同樣先看看遞迴版本:

public

class

solution

private

void

postordercore

(node root)

}

我們僅僅將list.add(root.val);這行**放到了遍歷子節點的for語句之後,意味著先將所有子節點加入結果列表,最後再將根節點加入結果列表。下面是使用迴圈的解法:

public

class

solution2

}return res;

}}

與前序遍歷不同的是我們不需要翻轉子節點列表,但是每次將結果新增到結果列表頭而不是尾。

第三題是層序遍歷(廣度優先搜尋),不像上面兩題用遞迴實現更加簡單,我們通過迴圈來實現會更加簡潔明瞭,思路是使用乙個佇列而非棧來儲存每一層節點:

public

class

solution

res.

add(list);}

return res;

}}

樹的遞迴,非遞迴,層序遍歷

長期以來,很多同學對數的遍歷都有一定的恐懼,其實多練練,多研究,發現是不難的,現在我來把數的構建,遞迴遍歷和非遞迴遍歷為大家整理一下,所有的 均為我自己敲出來的,並且經過了測試,希望給大家乙個參考,若有不足之處,歡迎指出交流。首先我把數存在陣列中,字子樹為空,則用 代替,根據這個陣列建立二叉樹的,然...

樹的遍歷,前中後 層次遍歷非遞迴

存在記憶體洩漏,原因是沒有銷毀結點時記憶體釋放的處理.include include include include using namespace std class cbtnode typedef cbtnode btnode class cbtroot void xianxubianli1 遞...

非遞迴實現樹的前中後遍歷

銜接bst樹的 可以放在一起執行測試 非遞迴先序 先根遍歷的基本思想就是 輸出自己,輸出左子樹,輸出右子樹。從根節點出發,向左依次輸出並進棧,當左孩子為空時,指標指向棧頂的右子樹,然後出棧,對右子樹進行遍歷。void pre output stack node root 到了從根節點出發,最左邊的節...