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 到了從根節點出發,最左邊的節...