二叉树前序、中序、后序的非递归(迭代)的统一化模板实现(python)

二叉树的前中后序遍历是面试过程中的高频考点,但是除了最简单的递归写法以外,面试官一般还会额外要求掌握其非递归写法(即迭代法)。

递归实现

三种遍历的递归实现非常相似,只需要掌握一个模板即可,只需要改变递归左子结点,根节点和右子结点的顺序即可完成三种树的递归遍历,其后序遍历的python代码如下所示:

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        def postorder(root: TreeNode):
            if not root:
                return
            #前中后序的顺序不同(只需更改下面三行的顺序即可实现三种不同的遍历的递归)
            postorder(root.left)
            postorder(root.right)
            res.append(root.val)
        
        res = list()
        postorder(root)
        return res

因为后序遍历结点的顺序是左右根的顺序,所以在递归的时候只需要以左右根的顺序进行递归或者保存就可以了,递归可以自动保存根节点在栈中(因为递归本身就可以看做是栈的一种特殊形式)。
以上代码如果切换到中序或者前序,也只需要将代码中注释的三行顺序更改为左根右或者根左右就可以了。

非递归实现(迭代)

往常的数据结构课程或者书本中都会给出三者对应的非递归实现,但是往往都是截然不同的,其中三种遍历方式中最简单的是中序遍历(左根右),其次是前序遍历(根左右),但是最复杂的后序遍历(左右根)需要格外的栈来记录父节点来保证回退的时候可以找到当前的遍历结点的父节点是谁。以下给出一个通用模板,可以像递归法一样只需要更改关键的顺序就可以完成三种遍历的非递归。其后续遍历的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]:
        res = []
        stack = [(False, root)]
        while stack:
            visit, node = stack.pop()
            if not node:
                continue
            if not visit:
                stack.append((True, node))
                stack.append((False, node.right))
                stack.append((False, node.left))
            else:
                res.append(node.val)
        return res

此代码也只需要更改左右根的入栈顺序就可以实现前中后三种二叉树的遍历。需要注意的是,因为该方法是使用stack来实现的入栈和出栈,因此入栈的顺序与遍历顺序是相反的,比如后序遍历的遍历顺序是左右根,但是入栈顺序要取反,变为根右左,中序和先序同理。
该方法实际上是对先序和中序遍历的非递归法做了一个复杂化(先序和中序实现的时候实际上是不需要用visit来标记根节点的访问情况的),由此和比较复杂的后序遍历使用统一的一个模板。

你可能感兴趣的