Leetcode 145 二叉树的后序遍历 迭代、递归、莫里斯算法 python实现

相关内容

给定一个二叉树,返回它的后序遍历。
在这里插入图片描述

# 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 postorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        def _postorderTraversal(root):
            if root:
                result.append(root.val)
                _postorderTraversal(root.right)
                _postorderTraversal(root.left)
        _postorderTraversal(root)
        return result[::-1]

	'''
	迭代法
	和递归法一样,得到中右左的结果,然后在倒过来成为左右中
	中右左的迭代和前序的迭代不同的是入栈的顺序
	前序是左子树入栈,出栈后进入右子树
	后序的迭代是右子树入栈,出栈后进入左子树
	将最终结果反向输出
	'''
	def postorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        current = root
        stack = []
        while stack or current:
            while current:
                 if current:
                     result.append(current.val)
                     stack.append(current)
                     current = current.right
            current = stack.pop()
            current = current.left
        return result[::-1]

	'''
	莫里斯算法
	莫里斯算法的后序遍历需要一个额外的空间,将该空间的左子树指向根节点
	然后依次找到每个根节点的中序前驱节点
	当第二次访问该节点时,倒叙输出从根节点左子树到前序节点的结果到最终结果上
	'''
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        dump = TreeNode()  # 新建空节点,空节点的左子树指向根节点
        dump.left = root
        result = []
        current = dump
        while current:
        	# 当没有左子树时转向右子树
        	# 因为当没有左子树时,按照后序左右中的顺序,已经没有左了,只需要考虑右和中就可以
            if not current.left:  
                current = current.right
            else:
           		# 当存在左子树时,找到根节点的中序前驱节点
           		# 并通过中序前驱节点本来应该是空的右子树判断是第几次访问根节点
                this = current.left  # 记录左子树的节点,待会得到输出结果
                pre = current.left
                while pre.right and pre.right!=current:
                    pre = pre.right
                if not pre.right:
                	# 当第一次访问根节点,
                	# 则将中序前驱节点的右子树指向根节点
                	# 当前节点指向左子树
                    pre.right = current
                    current = current.left
                else:
                	# 如果是第二次访问根节点了
                	# 则【倒着】输出从左子树到中序节点的结果
                	# 然后转到右子树
                	# 
                	# 假设是一颗2层的树
                	#          		0(临时节点)
                	#      		1
                	#  		2       3
                	# 当第二次访问根节点1 时
                	# 根结点1的中序前驱节点是2
                	# 则【倒着】输出从左子树2,到中序前驱2的路径结果,[2]
                	# 然后从根节点1到右子树3,3没有左子树然后转到右子树0(3是0的中序前序)
                	# 这是第二次访问0节点,然后【倒着】输出从左子树1到中序前序3的路径结果,[3,1]
                	# 按照这个顺序,实际上是依次获得左,然后倒着获得[右,中] ,
                	#
                	# 当第二次访问根节点时,已经获得了根节点左子树的全部节点,所以转到右子树
                	# 因为添加了临时节点,所以获得了根节点左子树、根节点右子树之后会回到临时节点的最高节点,
                	# 最高节点获得它的左子树的全部节点时会获得根节点的值
                    pre.right = None
                    temp = []
                    while this :
                        temp.append(this.val)
                        this = this.right
                    print(temp)
                    result.extend(temp[::-1])
                    current = current.right
        return result


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值