目录
一、问题描述
二叉树前序遍历的顺序是“根左右”,以下面这棵二叉树为例,前序遍历的结果应该是[1,2,4,5,3]
要确保自己会使用纸笔对二叉树进行前序遍历,然后再往下看。
下面是自定义的二叉树结点类:
class TreeNode:
'''二叉树结点类'''
def __init__(self,x):
# 当前节点的值
self.val = x
# 左孩子
self.left = None
# 右孩子
self.right = None
二、递归实现前序遍历
用递归的方式进行二叉树遍历非常简单,因为我们不需要考虑具体到每个结点的细节,只要把握整体思路就可以。先处理的是根节点,然后处理的是左子树,再处理右子树。至于程序是怎么处理左子树和右子树的,不用考虑,只要知道程序一定能按照正确的顺序处理左右子树就行了。
递归的出口呢?我们的“根左右”不会无限地进行下去,走到叶子节点,也就是没有孩子的节点的时候,就是收手的时候了。如何体现“没有孩子”?其实也就是碰到了None。那么出口就很明显了。当一个节点是None的时候,返回空列表。
以下是代码实现:
def preorder_rec(root:TreeNode)->list:
'''递归的方式进行前序遍历'''
if root is None:
return []
return [root.val]+preorder_rec(root.left)+preorder_rec(root.right)
三、迭代实现前序遍历
前序遍历的时候,处理了根以后,会处理整个左子树,也就是说,会一直深入遍历左子树,直到走到左子树的叶子节点,然后再回过头来处理右子树。这种“深入”的特点,让我们想到借用栈来保存未处理的节点。
因为栈有后入先出的特点,为了保证我们处理的时候是先左后右,我们往栈里压入结点的时候就一定要先压入右孩子,再压入左孩子。记住这个原则,代码的实现就不难了。
请看代码:
def preorder(root:TreeNode)->list:
'''迭代的方式进行前序遍历'''
if root is None:
return []
# 这个栈起辅助作用
stack = [root]
# 这是用来存放遍历结果的列表,也就是最终要返回的列表
ans = []
# 循环进行的条件是栈不为空
while stack:
top = stack.pop()
ans.append(top.val)
# 因为我们希望先处理左孩子,再处理右孩子
# 根据栈后进先出的特点,要先把右孩子压栈,再把左孩子压栈
if top.right:
stack.append(top.right)
if top.left:
stack.append(top.left)
return ans