引言
练习完二叉树的前序遍历、中序遍历、后序遍历三个算法之后,站在巨人的肩膀上,总结了一个算法,可以通用于前序、中序、后序遍历,记忆也超方便。
算法
class Solution:
def orderTraversal(self, root: TreeNode) -> List[int]:
ZERO, ONE= 0, 1
res = []
stack = [(ZERO, root)]
while stack:
color, node = stack.pop()
if node is None: continue
if color == ZERO:
# 以下是中序遍历的方式,对于前序、后序遍历,
# 只需要改变结点的入栈顺序即可
stack.append((ZERO, node.right))
stack.append((ONE, node))
stack.append((ZERO, node.left))
else:
res.append(node.val)
return res
算法分析
遍历方式
一个简单的二叉树模型:
中
/ \
左 右
三种遍历方式:
- 前序遍历:中,左,右
- 中序遍历:左,中,右
- 后序遍历:左,右,中
栈
1、栈是一种 “先进后出” 的结构
2、栈的抽象数据描述如下:
ADT Stack:
Stack(self) # 创建空栈
is_empty(self) # 判断栈是否为空
push(self, elem) # 将元素elem加入栈
pop(self) # 删除栈中最后加入的元素并将其返回
top(self) # 取得栈中最后压入的元素,不删除
3、栈大多基于线性表,而 Python 的 list 是线性表的一种实现,所以可以使用 list 作为栈元素存储区
4、栈的结构(类与方法):
class Stack(object):
def __init__(self):
self.stack = []
def push(self, data):
"""进栈函数"""
self.stack.append(data)
def pop(self):
"""出栈函数"""
return self.stack.pop()
def gettop(self):
"""取栈顶"""
return self.stack[-1]
算法核心思想
1、新结点为ZERO,已访问的结点为ONE
2、如果遇到的结点为ZERO,则将其标记为ONE
3、若是中序遍历,将其右子结点、本结点、左子结点依次入栈;若是前序遍历,将其右子结点、左子结点、本结点依次入栈;若是后序遍历,将其本结点、右子结点、左子结点依次入栈(这样出栈的时候才是正确的遍历顺序)
4、如果遇到的结点为ONE,则将结点的值输出