二叉树非递归前序遍历
最近重新学习DFS,觉得是时候把前序中序后序遍历的非递归写法整理一下了。。本文中的二叉树节点类定义如下:
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
1. Using 1 stack
O(n) time, O(n) space
方法1.1:
初始设置栈为空,当前节点为根节点
执行以下操作:
- 访问当前节点并入栈,将左子节点设为当前节点,直到当前节点为空。
- 弹出栈顶,将当前节点设置为弹出节点的右子节点。
直到栈为空且当前节点为空时停止
stack = []
node = root
while stack or node:
if node:
print(node.val)
stack.append(node)
node = node.left
else:
node = stack.pop()
node = node.right
方法1.2
假设根节点非空,初始将根节点入栈
执行以下操作:
- 弹出栈顶作为当前节点,并访问
- 如果当前节点的子节点非空,反序入栈
直到栈为空时停止
stack = [root]
while stack:
node = stack.pop()
print(node.val)
if node.right: stack.append(node.right)
if node.left: stack.append(node.left)
2. Using 2 stacks
O(n) time, O(n) space
stack: 用于储存和遍历子节点,初始化=[root]
path: 记录从根节点到当前节点的路径
执行以下操作:
- node = stack.peek
- 如果stack和path栈顶元素不同:
– 访问node,入栈path
– node的子节点反序入栈stack - 如果stack和path栈顶元素相同:(到了叶节点,需要回头)
–stack和path弹出栈顶
直到stack为空
stack = [root]
path = []
while stack:
node = stack[-1]
if path and path[-1] == node:
path.pop()
stack.pop()
else:
print(node.val)
path.append(node)
if node.right: stack.append(node.right)
if node.left: stack.append(node.left)
3. Using no stacks (Morris traversal)
O(n) time, O(1) space
Morris traversal 利用叶节点指向左右孩子的空指针,临时修改指向从而保存后继节点信息,之后访问修改过的节点时可以恢复树的结构。
初始设置node = root
进行以下操作直到node为空:
- 如果当前节点node的左孩子非空,找到中序遍历的前驱节点,左孩子的最右后代
– 如果前驱节点的右孩子为空,访问当前节点,将前驱节点的右孩子设置为当前节点。更新 node = node.left
– 如果前驱节点的右孩子非空(则为当前节点),将右孩子重新设置为空,恢复树的形状。更新 node = node.right - 如果node的左孩子为空,则访问当前节点,更新 node = node.right
node = root
while node:
if node.left:
prev = node.left
while prev.right and prev.right != node:
prev = prev.right
if not prev.right:
print(node.val)
prev.right = node
node = node.left
else:
prev.right = None
node = node.right
else:
print(node.val)
node = node.right
参考资料:
https://leetcode.com/problems/binary-tree-preorder-traversal/discuss/45312/three-ways-of-iterative-preorder-traversing-easy-explanation
https://www.cnblogs.com/anniekim/archive/2013/06/15/morristraversal.html
https://blog.csdn.net/My_Jobs/article/details/43451187