leetcode 94、144,、145:二叉树的中序、先序、后序遍历

本文介绍了Morris遍历方法,这是一种在二叉树遍历中实现O(n)时间复杂度和O(1)空间复杂度的高效算法。通过利用空指针,该方法避免了使用额外的数据结构。详细讲解了中序、先序和后序遍历的实现过程,并提供了相应的Python代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用递归和迭代的思想完成二叉树的遍历,在时间复杂度和空间复杂度上都是O(n)和O(n)。Morris提出了一种遍历的方式,使得遍历可以在线性时间、常数空间上完成遍历,即O(n)和O(1),它的核心思想就是利用树中大量的空指针,实现空间的缩减。
具体地,按照思想,先中序遍历
1. 如果当前结点的左节点为空,输出当前结点,设置当前结点为其右节点
2. 如果当前结点的左节点不为空:寻找当前结点的左子树的最右结点predecessor(也就是中序遍历是的前一个结点)
1) 如果predecessor的右指针为空,将其右指针设置为当前结点,当前结点设置为其左节点
2) 如果predecessor的右指针不为空,将该指针恢复为空,输出当前结点,并将当前结点设置为其右节点
循环1.2
提示:predecessor即当前结点向左走一步,然后一直向右走直到无法走为止

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result = []
        if not root:
            return result
        while root:  # 用root来标记当前结点
            if root.left is None:
                result.append(root.val)
                root = root.right
            else:
                predecessor = root.left
                while predecessor.right and predecessor.right != root:
                    predecessor = predecessor.right
                if predecessor.right is None:
                    predecessor.right = root
                    root = root.left
                else:
                    predecessor.right = None
                    result.append(root.val)
                    root = root.right
        return result

先序遍历: 和中序遍历对比着记忆
1. 如果当前结点的左节点为空,输出当前结点, 设置当前结点为其右节点
2. 如果当前结点的左节点不为空:寻找当前结点的左子树的最右结点predecessor(也就是中序遍历是的前一个结点)
1) 如果predecessor的右指针为空,将其右指针设置为当前结点,输出当前结点, 当前结点设置为其左节点
2) 如果predecessor的右指针不为空,将该指针恢复为空,并将当前结点设置为其右节点
循环1.2
提示:predecessor即当前结点向左走一步,然后一直向右走直到无法走为止

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result = []
        if not root:
            return result
        while root:  # 用root来标记当前结点
            if root.left is None:
                result.append(root.val)
                root = root.right
            else:
                predecessor = root.left
                while predecessor.right and predecessor.right != root:
                    predecessor = predecessor.right
                if predecessor.right is None:
                    predecessor.right = root
                    result.append(root.val)
                    root = root.left
                else:
                    predecessor.right = None
                    root = root.right
        return result

后序遍历: 要新建一个临时结点,也要对比着记
设置一个临时结点root,令其左节点为根节点
1. 如果当前结点的左节点为空,设置当前结点为其右节点
2. 如果当前结点的左节点不为空:寻找当前结点的左子树的最右结点predecessor(也就是中序遍历是的前一个结点)
1) 如果predecessor的右指针为空,将其右指针设置为当前结点,当前结点设置为其左节点
2) 如果predecessor的右指针不为空,将该指针恢复为空,倒序输出从当前结点的左节点到predecessor路径上的所有结点,并将当前结点设置为其右节点
循环1.2
提示:·predecessor即当前结点向左走一步,然后一直向右走直到无法走为止
·从当前结点的左节点到predecessor路径上的所有结点——从当前结点一直向右直到为predecessor

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def postorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result = []
        if not root:
            return result
        r = TreeNode()
        r.left = root
        root = r
        while root:  # 用root来标记当前结点
            if root.left is None:
                root = root.right
            else:
                predecessor = root.left
                while predecessor.right and predecessor.right != root:
                    predecessor = predecessor.right
                if predecessor.right is None:
                    predecessor.right = root
                    root = root.left
                else:
                    predecessor.right = None
                    # 倒序输出,因为使用这种方法的目的是减少空间的使用,所以这里在倒序的时候,不能再使用一个数组完成
                    # dao = []
                    # temp = root.left
                    # while temp != predecessor:
                    #     dao.append(temp.val)
                    #     temp = temp.right
                    # dao.append(predecessor.val)
                    # dao = dao[::-1]
                    # for i in range(len(dao)):
                    #     result.append(dao[i])
                    temp = root.left
                    count = 0
                    while temp:  # predecessor一定是最后一个right不然它不可能是predecessor
                        count += 1
                        result.append(temp.val)
                        temp = temp.right
                    # 完成倒序:
                    i = len(result) - count
                    j = len(result) - 1
                    while i < j:
                        temp_0 = result[i]
                        result[i] = result[j]
                        result[j] = temp_0
                        i += 1
                        j -= 1
                    root = root.right
        return result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值