用系统堆栈实现(递归)
很容易实现:
- 前序:do(), 递归左儿子, 递归右儿子
- 中序:递归左儿子, do(), 递归右儿子
- 后序:递归左儿子, 递归右儿子, do()
用自定义栈实现(迭代法)
首先首先首先!!!
明确前中后序遍历的本质,即二叉树节点的访问顺序:
- 前序:中 -> 左 -> 右
- 中序:左 -> 中 -> 右
- 后序:左 -> 右 -> 中
中代表直接访问了一次该节点,左右代表访问一次其左右儿子
随想录链接:https://programmercarl.com/二叉树的迭代遍历.html#前序遍历-迭代法
前序的写法:
模拟递归法即可,唯一需要注意点就是,因为用的自己的栈,故如果想先左后右,那么必须先入栈右儿子
点击查看代码
while len(stack) != 0:
res.append(stack[-1].val)
node = stack.pop()
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
中序的写法:
我最开始思路就是,不就是再模拟一次递归就好?故调整左右儿子入栈顺序。太天真了
其实前序遍历写法简单的关键在访问与处理刚好都是第一步,而中序是第二次访问才开始处理
故应该分步负责访问和处理
- 用一个指针负责访问
- 用栈维护处理节点的功能
p = root
while p or stack:
if p:
stack.append(p)
p = p.left
else:
p = stack.pop()
res.append(p.val)
p = p.right
后序的写法:
这个是完全学习的随想录,实在没思路了。
先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
故调整下前序法的顺序(注意先右后左):
while len(stack) != 0:
res.append(stack[-1].val)
node = stack.pop()
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
最后来个res.reverse()