相关内容
给定一个二叉树,返回它的前序遍历。
具体的结题思路见代码注释
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
'''
迭代法
迭代法维护了一个堆栈,以此记录了从前序中左右从高层根节点到底层叶子节点的顺序,
并且根据中左右,在第一次访问根节点的时候就把结果输出
记录的堆栈的目的是从底层叶子返回根节点然后到右子树上
'''
def preorderTraversal(self, root: TreeNode) -> List[int]:
result = []
stack = []
current = root
while stack or current:
while current:
result.append(current.val)
stack.append(current)
current = current.left
current = stack.pop()
current = current.right
return result
'''
递归法
递归法判断当前节点是否为空
当不为空是依次按照中、左、右的顺讯进行遍历,其中中就直接输出
'''
def preorderTraversal(self, root: TreeNode) -> List[int]:
result = []
def _preorderTraversal(root):
if root:
result.append(root.val)
_preorderTraversal(root.left)
_preorderTraversal(root.right)
_preorderTraversal(root)
return result
'''
莫里斯算法
莫里斯算法对于每一个节点将该节点的中序前驱节点(左子树上最右的叶子节点)的空右子树的内存指向自己
作为从底层叶子节点返回高层根节点的途径。
在迭代法中需要维护一个堆栈,作为从中到左,之后以此退栈实现从左子树回到根节点然后在进行向右子树的递归
'''
def preorderTraversal(self, root: TreeNode) -> List[int]:
self.result = []
current = root # 当前节点设置为根节点
while current:
if not current.left: # 前序遍历是中左右的顺序,当没有左子树时,直接输出值,并转到右子树上
self.result.append(current.val)
current = current.right
else: # 当存在左子树时,找到根节点的中序前驱节点,也就是左子树的最右的叶子
pre = current.left
while pre.right and pre.right!=current: # 判断左子树的最右叶子的右子树(本来是空内存)是否为空
pre = pre.right
if not pre.right:
# 当右子树是空,说明该根节点是第一次被访问
# 按照前序 中左右,根节点第一次被访问时就应该输出
#
# 前序和中序遍历不一样的地方在于,中序遍历是左中右,是从中到左到中的时候才将根节点输出
# 所以中序遍历是在第二次访问节点是输出
#
# 第一次访问根节点时,将中序前驱节点的右子树空内存指向根节点
# 然后按照中左右的顺序,访问了根节点就需要左子树,将当前节点转向左子树,
self.result.append(current.val)
pre.right = current
current = current.left
else:
# 此时中序前驱节点的右子树的本来是空的内存已经指向了根节点
# 说明当前的根节点,已经是从左子树访问完了又回到了根节点,第二次访问根节点了
# 此时就需要将中序前序节点的右子树的内存值为空,回到最初树的形状
# 然后当前节点转向右子树
pre.right = None
current = current.right
return self.result