二叉树遍历框架(递归与非递归)

1.递归写法

递归写法很简单,只需按根出现的顺序改变将根节点加入返回结果的顺序(递归调用前/中/后)即可。

1.1.前序

# 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]:
        ret=[]
        def helper(root):
            if not root:
                return
            ret.append(root.val)
            helper(root.left)
            helper(root.right)
        helper(root)
        return ret

1.2.中序

# 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]:
        ret=[]
        def helper(root):
            if not root:
                return
            helper(root.left)
            ret.append(root.val)
            helper(root.right)
        helper(root)
        return ret

1.3.后序

# 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]:
        ret=[]
        def helper(root):
            if not root:
                return
            helper(root.left)
            helper(root.right)
            ret.append(root.val)
        helper(root)
        return ret

2.非递归写法

非递归写法中,需要额外用一个list模拟栈(stack)来记录节点的访问状态,同时用一个list(ret)记录遍历结果。下面用一种统一且方便记忆的框架来实现二叉树的非递归遍历。

1.1.前序

前序遍历即根左右的方式遍历二叉树。最后得到的遍历结果为:(根1)(左1)(右1) --> (根1)(根2左2右2)(根3左3右3) --> ...,即:

  1. 若根节点非空,将其左子节点同时加入res和stack中,更新根节点为其左子节点;
  2. 若根节点为空,弹出stack栈顶元素,如果该元素有右子节点,将根节点更新为其右子节点。重复1,直到stack为空。代码如下:
# 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]:
        ret=[]
        stack=[]
        # 栈非空,排除初始条件
        while root or stack:
            # 更新root同时加入ret和stack
            while root:
                ret.append(root.val)
                stack.append(root)
                root=root.left
            # 遍历右子节点
            if stack:
                node=stack.pop()
                if node.right:
                    # 从右子节点开始循环
                    root=node.right
        return ret

1.2.后序

因为后续的遍历顺序为:左右根,而前序为根左右。如果我们在前序遍历的时候先遍历右子树,那么就能得到根右左的顺序,再将其逆序,就能得到后序遍历的结果。代码如下:

# 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]:
        ret=[]
        stack=[]
        while root or stack:
            while root:
                ret.append(root.val)
                stack.append(root)
                # 先处理右子树
                root=root.right
            if stack:
                node=stack.pop()
                # 再处理左子树
                if node.left:
                    root=node.left
        # 逆序
        return ret[::-1]

1.3.中序

中序遍历的顺序是左根右,和前序遍历类似,但不同的一点是,只有当从stack弹出元素时,我们才遍历这个节点
一个很直观的理解是:中序遍历的第一个元素是最左边节点的值,所以是用左子节点更新根节点时压入stack的最后一个元素,即第一次不满足条件时弹出的那个元素。代码如下:

# 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 inorderTraversal(self, root: TreeNode) -> List[int]:
        ret=[]
        stack=[]
        while root or stack:
            while root:
                stack.append(root)
                root=root.left
            if stack:
                node=stack.pop()
                # 从栈弹出时遍历
                ret.append(node.val)
                if node.right:
                    root=node.right
        return ret
posted @ 2020-09-21 20:49  backtosouth  阅读(164)  评论(0编辑  收藏  举报