leetcode-二叉樹的前中後遍歷(94、144、145)
阿新 • • 發佈:2019-01-14
中序遍歷
中序遍歷的順序:左中右
思路
- 遞迴
每次遞迴,只需要判斷結點是不是None,否則按照左中右的順序打印出結點value值
class Solution:
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return self.inorderTraversal( root.left) + [root.val] + self.inorderTraversal(root.right)
- 迴圈
迴圈比遞迴要複雜得多,因為你得在一個函式中遍歷到所有結點。
對於樹的遍歷,迴圈操作基本上要用到棧(stack)這個結構
對於中序遍歷的迴圈實現,每次將當前結點(curr)的左子結點push到棧中,直到當前結點(curr)為None。這時,pop出棧頂的第一個元素,設其為當前結點,並輸出該結點的value值,且開始遍歷該結點的右子樹。
規律為:當前結點curr不為None時,每一次迴圈將當前結點curr入棧;當前結點curr為None時,則出棧一個結點,且打印出棧結點的value值。整個迴圈在stack和curr皆為None的時候結束。
class Solution:
def inorderTraversal(self, root):
stack = []
sol = []
curr = root
while stack or curr:
if curr:
stack.append(curr)
curr = curr.left
else:
curr = stack.pop()
sol. append(curr.val)
curr = curr.right
return sol
前序和後序
前序遍歷指根結點在最前面輸出,所以前序遍歷的順序是:中左右
後序遍歷指根結點在最後面輸出,所以後序遍歷的順序是:左右中
遞迴
class Solution:
def preorderTraversal(self, root): ##前序遍歷
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return [root.val] + self.inorderTraversal(root.left) + self.inorderTraversal(root.right)
def postorderTraversal(self, root): ##後序遍歷
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return self.inorderTraversal(root.left) + self.inorderTraversal(root.right) + [root.val]
迴圈
先看前序遍歷。我們仍然使用棧stack,由於前序遍歷的順序是中左右,所以我們每次先列印當前結點curr,並將右子結點push到棧中,然後將左子結點設為當前結點。入棧和出棧條件(當前結點curr不為None時,每一次迴圈將當前結點curr入棧;當前結點curr為None時,則出棧一個結點)以及迴圈結束條件(整個迴圈在stack和curr皆為None的時候結束)與中序遍歷一模一樣。
再看後序遍歷。由於後序遍歷的順序是左右中,我們把它反過來,則遍歷順序變成中左右,是不是跟前序遍歷只有左右結點的差異了呢?然而左右的差異僅僅就是.left和.right的差異,在程式碼上只有機械的差別。
class Solution:
def preorderTraversal(self, root): ## 前序遍歷
stack = []
sol = []
curr = root
while stack or curr:
if curr:
sol.append(curr.val)
stack.append(curr.right)
curr = curr.left
else:
curr = stack.pop()
return sol
def postorderTraversal(self, root): ## 後序遍歷
stack = []
sol = []
curr = root
while stack or curr:
if curr:
sol.append(curr.val)
stack.append(curr.left)
curr = curr.right
else:
curr = stack.pop()
return sol[::-1]