二叉树的各种遍历(非递归实现版本)

本文详细介绍了二叉树的三种遍历方法:先序遍历、中序遍历和后序遍历。每种方法都提供了多种实现思路,并通过代码示例深入解析了遍历过程。此外,还对比了不同遍历方法的特点,帮助读者全面理解二叉树遍历算法。

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

  • 先序遍历
class TreeNode(object):
     def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None
class Solution(object):
    # method 1
    def preorderTraversal_1(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = []
        res = []
        if root:
            stack.append(root)
        while(stack):
            x=stack.pop(-1)
            res.append(x.val)
            if x.right:
                stack.append(x.right)
            if x.left:
                stack.append(x.left)
        print(res)
        return res
    # method 2
    def preorderTraversal_2(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = []
        res = []
        while 1:
            while root:
                res.append(root.val)
                stack.append(root.right)
                root = root.left
            if stack==[]:
                break
            root = stack.pop(-1)
        print(res)
        return res
    # method 3
    def preorderTraversal_3(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = []
        res = []
        while 1:
            while root:
                res.append(root.val)
                stack.append(root)
                root = root.left
            if stack==[]:
                break
            root = stack.pop(-1)
            root = root.right
        print(res)
        return res



if __name__ == '__main__':
    S = Solution()
    l1 = TreeNode(1)
    l2 = TreeNode(2)
    l3 = TreeNode(3)
    l4 = TreeNode(4)
    l5 = TreeNode(5)
    l6 = TreeNode(6)
    l7 = TreeNode(7)
    root = l1
    l1.left = l2
    l1.right = l3
    l2.left = l4
    l2.right = l5
    l3.left = l6
    l3.right = l7
    z = S.preorderTraversal_1(root)

对于方法1,思路是,首先把根节点入栈,然后在循环里面:首先把根节点出栈,并访问根节点的值;判断根节点是否存在右孩子和左孩子(右顾左盼),并把右孩子和左孩子依次入栈,重新进入循环,根据FILO原则,左孩子先出栈,并访问其值;再判断左孩子的左右孩子情况,不断迭代。如下图所示:

对于方法2,思路是,在内层while循环里,从根节点开始,首次访问该节点,然后把该节点的右孩子入栈,不断向左走,直到某个节点没有左孩子。这个时候,元素出栈,第一次出来的是最左边节点的右孩子(如果存在右孩子的话;不存在时出栈的是其父节点的右孩子)。外面的大循环就是使得每次从出栈的右孩子开始,继续按照沿着左侧链走的思想进行下去。算法退出的条件是栈为空。如下图所示:

对于方法3,思路其实和法2差不多,只不过入栈的是左侧链的节点本身。在左侧链走到底后,栈弹出来一个元素,并把该元素的右孩子重新传递内层循环的条件,再次按左侧链迭代。算法退出的条件是栈为空。

  • 中序遍历
class TreeNode(object):
     def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None
class Solution(object):
    def inorderTraversal_1(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = []
        res = []
        while 1:
            while root:
                stack.append(root)
                root = root.left
            if stack==[]:
                break
            root = stack.pop(-1)
            res.append(root.val)
            root = root.right
        print(res)
        return res
if __name__ == '__main__':
    S = Solution()
    l1 = TreeNode(1)
    l2 = TreeNode(2)
    l3 = TreeNode(3)
    l4 = TreeNode(4)
    l5 = TreeNode(5)
    l6 = TreeNode(6)
    l7 = TreeNode(7)
    root = l1
    l1.left = l2
    l1.right = l3
    l2.left = l4
    l2.right = l5
    l3.left = l6
    l3.right = l7
    z = S.inorderTraversal_1(root)

中序遍历的思路和先序遍历的思路3类型,首先是先沿着左侧链走,把沿途节点进栈,在达到最左端后,出栈,并访问其值,然后把该节点的右孩子赋给内层循环的变量,在右孩子处继续按左侧链思路走下去。直到栈空。如下图所示:

  • 后序遍历
class TreeNode(object):
     def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None
class Solution(object):
    # 借鉴前序遍历方法1的思路,最后把结果逆转
    def postorderTraversal_1(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res=[]
        stack = [root]
        while stack:
            t = stack.pop()
            if t:
                res.append(t.val)
                stack.append(t.left)
                stack.append(t.right)
        print(res[::-1])
        return res[::-1]
    # 节点加一个标志符号组成二元组,构成栈的元素
    def postorderTraversal_2(self, root):
        res=[]
        stack=[(root,False)]
        while stack:
            t,flag = stack.pop()
            if t:
                if flag:
                    res.append(t.val)
                else:
                    stack.append((t, True))
                    stack.append((t.right, False))
                    stack.append((t.left, False))
        print(res)
        return res
    def postorderTraversal_3(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res=[]
        stack = [root]
        while stack:
            t = stack.pop()
            if type(t) is TreeNode:
                stack.append(t.val)
                if t.right:
                    stack.append(t.right)
                if t.left:
                    stack.append(t.left)
            else:
                res.append(t)
        print(res)
        return res

    def postorderTraversal_4(self, root):
        res=[]
        if not root:
            return
        stackNode = []
        markNode = None
        node = root
        while stackNode or node:
           while node:
            stackNode.append(node)
            node = node.left
           node = stackNode.pop()
           if not node.right or node.right is markNode:
            #node  has no rightNode or node's rightNode has been checked
            res.append(node.val)
            markNode = node
            node = None
           else:
            stackNode.append(node)
            node = node.right
        print(res)
        return res
if __name__ == '__main__':
    S = Solution()
    l1 = TreeNode(1)
    l2 = TreeNode(2)
    l3 = TreeNode(3)
    l4 = TreeNode(4)
    l5 = TreeNode(5)
    l6 = TreeNode(6)
    l7 = TreeNode(7)
    root = l1
    l1.left = l2
    l1.right = l3
    l2.left = l4
    l2.right = l5
    l3.left = l6
    l3.right = l7
    z = S.postorderTraversal_1(root)

思路一:类似于先序遍历的方法一,首先根节点入栈,然后在大循环里出栈,并访问其值, 接着左孩子入栈,右孩子入栈;回到循环处,继续出栈、访问。。。最终结果刚好是后序遍历的逆序,所以反转后即可。

思路二:节点加一个标志符号组成二元组,构成栈的元素,首先根节点出栈,然后判断FALG是否为TRUE,否,则重新入栈,并令其flag为true,并把其右孩子,左孩子入栈,且其FLAG初始值均为False;接着继续进行上述操作,直到最左边的节点入栈,值为false,此时其出栈后判断再进栈变为true,此时无孩子入栈,继续循环,此时为true了,所以直接append结果;一直循环即可。

参考资料:https://blog.youkuaiyun.com/yangjingjing9/article/details/77054899

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值