深度優選遍歷有三種形式,先序遍歷、中序、後序遍歷。我們一般是用遞歸寫的,因爲好寫也好理解。但偏偏在面試的時候,面試官可能要我們寫迭代的寫法。先序遍歷的迭代寫法很好寫。但是另外兩種就沒那種容易一下就寫出來的。
參考了leetcode解法,這裏總結一下。
統一的框架
先序遍歷
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack = []
if not root:
return []
stack.append(root)
res = []
while stack:
p = stack.pop()
if p:
if p.right: # 先加入右子節點
stack.append(p.right)
if p.left: # 再加入左子節點
stack.append(p.left)
stack.append(p) # 再次加入當前節點
stack.append(None) # 用None代表stack之前的一個位置是已經訪問過了
else: # 找到了一個訪問過的位置
res.append(stack.pop().val)
return res
因爲用棧,先序遍歷要求先走根節點,再走左節點。後壓入左子節點,爲的是下次迭代先pop出的是左子節點。
大家也許會覺得None沒有意義。但實際上,爲了統一框架,None還是有意義的。當我們在寫中序遍歷和後序遍歷的時候,None的作用就是很大的了。
中序遍歷
僅僅更改註釋的地方
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack = []
if not root:
return []
stack.append(root)
res = []
while stack:
p = stack.pop()
if p:
if p.right:
stack.append(p.right)
stack.append(p) # 再次在加完右子節點之後,加入當前節點
stack.append(None) # 加入訪問的標誌
if p.left:
stack.append(p.left)
else:
res.append(stack.pop().val)
return res
後序遍歷
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack = []
if not root:
return []
stack.append(root)
res = []
while stack:
p = stack.pop()
if p:
stack.append(p) # 先加入訪問過的節點
stack.append(None) # 加入訪問的標誌
if p.right:
stack.append(p.right)
if p.left:
stack.append(p.left)
else:
res.append(stack.pop().val)
return res