Leetcode-144 二叉树的前序遍历的三种方式-迭代、递归、莫里斯,Python实现

相关内容

给定一个二叉树,返回它的前序遍历。
在这里插入图片描述
具体的结题思路见代码注释

# 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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值