二叉树遍历以及延伸
1. 二叉树先序、中序、后序层次遍历
1.1. 先序遍历
1.1.1. 递归实现
# traversal用于递归,preorderTravelsal中使用res用于保存递归的输出结果。
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def traversal(self, res, root):
if root:
res.append(root.val)
self.traversal(res, root.left)
self.traversal(res, root.right)
def preorderTraversal(self, root: TreeNode):
res = []
self.traversal(res, root)
return res 1.1.2. 非递归写法
过程:
- 初始化栈stack,将根节点添加到栈中
- 当栈不为空时
- 弹出栈顶元素tmp,并将值添加到res中。
- tmp右子树非空,将右子树入栈。
- tmp左子树非空,将左子树入栈。
由于栈是“先进后出”的顺序,所以右子树先入栈,从而使得结果为“根-左-右”。
class Solution:
def preorderTraversal(self, root: TreeNode):
if root is None:
return []
res, stack = [], [root]
while stack:
tmp = stack.pop() # 弹出栈顶元素
if tmp:
res.append(tmp.val) # 输出根值
if tmp.right:
stack.append(tmp.right)
if tmp.left:
stack.append(tmp.left)
return res 小结:递归实现时,是函数自己调用自己,一层层的嵌套下去,操作系统自动帮我们用 栈 来保存每个调用的函数,而非递归就需要我们自己模拟这样的调用过程。
1.1.3. 模板解法
参考here
思路:
- 首先,将所有根节点root的所有左孩子入栈并将值加入到结果中,直至root为空。
- 然后每弹出一个栈顶元素tmp,就访问它的右孩子。然后在将该节点当做root重新按照步骤1来一遍,直至栈为空。
class Solution:
def preorderTraversal(self, root: TreeNode):
if root is None:
return []
res, stack = [], []
while stack or root:
while root: # 循环直至所有左孩子入栈
res.append(root.val) # 值加入到res中
stack.append(root)
root = root.left
tmp = stack.pop()
root = tmp.right
return res 1.2. 中序遍历
1.2.1. 递归实现
思路:只是在递归的时候修改访问顺序即可,可以对比先序遍历的递归代码。
# 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
class Solution:
def traversal(self, res, root):
if root:
self.traversal(res, root.left)
res.append(root.val)
self.traversal(res, root.right)
def inorderTraversal(self, root: TreeNode):
if root is None:
return []
res = []
self.traversal(res, root)
return res 1.2.2. 非递归实现
思路:参考动画演示
由于中序遍历是左-根-右,因此,首先需要找到最左侧的节点的位置,然后输出该节点的值。然后将该节点右侧压入栈中,重复操作,直至栈空或root为空。
class Solution:
def inorderTraversal(self, root: TreeNode):
if root is None:
return []
res, stack = [], []
while stack or root:
if root:
stack.append(root)
root = root.left
else:
tmp = stack.pop()
res.append(tmp.val)
root = tmp.right
return res 1.2.3. 模板解法
相对于先序遍历的解法,只用修改一下res.append()的位置在pop()之后即可。
class Solution:
def inorderTraversal(self, root: TreeNode):
if root is None:
return []
res, stack = [], []
while stack or root:
while root:
stack.append(root)
root = root.left
tmp = stack.pop()
res.append(tmp.val)
root = tmp.right
return res 1.3. 后序遍历
1.3.1. 递归实现
class Solution:
def postorderTraversal(self, root: TreeNode):
res = []
self.traversal(res, root)
return res
def traversal(self, res, root):
if root:
self.traversal(res, root.left)
self.traversal(res, root.right)
res.append(root.val) 1.3.2. 非递归实现
思路:与先序遍历的非递归实现很相似,在压入栈的时候,先压入左子树,在压入右子树,同时最后返回值的时候返回res的倒序。
class Solution:
def postorderTraversal(self, root: TreeNode):
if not root:
return []
res, stack = [], [root]
while stack:
tmp = stack.pop()
res.append(tmp.val)
if tmp.left:
stack.append(tmp.left)
if tmp.right:
stack.append(tmp.right)
return res[::-1] 1.3.3. 模板解法
思路:与前序遍历相比,修改里层while循环的left->right,外层while循环的right->left,然后res逆序即可。
class Solution:
def postorderTraversal(self, root: TreeNode):
if root is None:
return []
res, stack = [], []
while stack or root:
while root:
stack.append(root)
res.append(root.val)
root = root.right
tmp = stack.pop()
root = tmp.left
return res[::-1] 1.4. 层次遍历
1.4.1. 递归实现
class Solution:
def helper(self, root, level, levels):
"""
levels:保存每一层的值。
level: 表示当前所在层数。根节点在第0层。
root:表示每次递归时的根节点。
"""
# 当level与len(levels)相等时,此时表示该层还没有创建对应的list用来保存该层的数值,
# 因此在levels最后增加一个索引为level的空list。
if level == len(levels):
levels.append([])
levels[level].append(root.val) # 将树节点对应的值放在对应的层次。
if root.left:
self.helper(root.left, level+1, levels) # 这里表示遍历对应的左子树。
if root.right:
self.helper(root.right, level+1, levels)
def levelOrder(self, root: TreeNode):
levels = []
self.helper(root, 0, levels)
return levels 输入和输出结果
1 / \ 2 3 / / 4 5 输出:[[1], [2, 3], [4, 5]]
修改上面代码,使的当不存在左子树或右子树的时候,就是用None替代
class Solution:
def helper(self, root, level, levels):
if level == len(levels):
levels.append([])
if root:
levels[level].append(root.val) # 将树节点对应的值放在对应的层次。
self.helper(root.left, level + 1, levels) # 这里表示遍历对应的左子树。
self.helper(root.right, level + 1, levels)
else:
levels[level].append(None)
def levelOrder(self, root: TreeNode):
levels = []
self.helper(root, 0, levels)
return levels[:-1] # 最后一列会保存多余的None,因此将其删掉。 输入和输出结果
1 / \ 2 3 / / 4 5 输出:[[1], [2, 3], [4, None, 6, None]]
1.4.2. 非递归实现(迭代实现)
二叉树的层次遍历的迭代方法与前面的不同,前面的方法都采用深度优先搜索的方式,而层次遍历使用广度优先搜索,广度优先搜索主要使用 队列 实现,因此前面的模板解法就不可使用了。
步骤:
- 初始化队列queue,并将根节点保存在添加到队列中。
- 当队列不为空时:
- 计算队列里面元素的长度size
- 循环size,保存结果到level中
- 同时添加左右子树到队列中。
- 当遍历到size之后,就将level添加到res中。
class Solution:
def levelOrder(self, root: TreeNode):
if not root:
return []
res, queue = [], [root]
while queue:
size = len(queue) # 当前队列中的节点数
level = [] # 分层存储
for i in range(size): # 遍历size次,也就是将该层所有节点的值都保存在level中
tmp = queue.pop()
level.append(tmp.val)
if tmp.left:
queue.insert(0, tmp.left)
if tmp.right:
queue.insert(0, tmp.right)
res.append(level)
return res 

360集团公司氛围 354人发布