名称记忆
关于名称记忆,前中后的意思是根节点的位置,前序遍历就是根节点在前,也就是中左右;中序遍历就是根节点在中间,也就是左中右;后序遍历也就是根节点在后,也就是左右中。
递归
以中序遍历为例,定义一个迭代函数,按照中序定义的方式去调用下方的节点
res = []
def search(root):
search(root.left)
res.append(root.val)
search(root.right)
然后加上终止条件,某个节点为空则返回上一层
res = []
def search(root):
if not root:
return
search(root.left)
res.append(root.val)
search(root.right)
前序后序类似,仅仅需要调整遍历函数中append的位置,风格上很统一
迭代
迭代不统一
前序遍历(中左右)
以先处理根节点的前序遍历为例子,由于先处理根节点,所以在一个节点出栈之后必须紧跟子节点入栈(中左右,对应入栈顺序就是右左),具体逻辑为:
构建初始栈(初始root进栈)
构建接受结果列表
循环(循环条件:栈不空)
出栈(出栈节点记录为node) 并记录节点值添加到结果列表中
node右节点如果存在:入栈
node左节点如果存在:入栈
出结果
if not root:
return []
stack = [root]
res = []
while stack:
node = stack.pop()
# 中
res.append(node.val)
# 右边先入栈
if node.right:
stack.append(node.right)
# 左边再入栈
if node.left:
stack.append(node.left)
return res
中序遍历(左中右)
stack = []
res = []
cur = root
while stack or cur:
if cur:
stack.append(cur)
cur = cur.left
else:
cur = stack.pop()
# 左边处理完了自然轮到中
res.append(cur.val)
# 中完了是右
cur = cur.right
return res
后续遍历(左右中)
针对前序遍历(中左右),调整下入栈的左右顺序,使其变为(中右左),然后再翻转一下变为(左右中即可)
if not root:
return []
stack = [root]
res = []
while stack:
node = stack.pop()
# 中
res.append(node.val)
# 左边先入栈
if node.left:
stack.append(node.left)
# 右边再入栈
if node.right:
stack.append(node.right)
return res[::-1]