二叉树的遍历:递归遍历和统一迭代遍历。

1.二叉树的定义

 二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成,如图1所示。图1

图1:二叉树

2.二叉树的遍历

 当我们在写代码使用树这种结构时,需要对树进行一些操作。其中,最基础的操作就是遍历。树的遍历一般分为,前序遍历中序遍历层次遍历。我们通常把树分为三部分,即左子树、根节点(中间节点)和右节点。根据访问顺序的不同定义除了不同的遍历。以图1为例展示不同遍历的结果。
前序遍历的顺序:根节点->左子树->右节点,1 2 4 5 3。
中序遍历的顺序:左子树->根节点->右节点,4 2 5 1 3。
后序遍历的顺序:左子树->右节点->根节点,4 5 2 3 1。

3.遍历的代码实现

一般来说,遍历的实现存在递归法迭代法两种。

3.1递归法

 优点:代码少,易理解。
 缺点:但是容易造成栈的溢出。此外因为要不断的调用函数,所以其需要的运行空间较大。
代码如下:

# Definition for a binary tree node.
from typing import Optional


# 节点类
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val  # 节点的值
        self.left = left  # 节点的左孩子
        self.right = right  # 节点的右孩子


# 前序遍历:中、左、右
def preordertraversal(root: Optional[TreeNode]) -> list[int]:
    def traversal(node):
        if node == None:  # 递归出口
            return
        result.append(node.val)  # 中
        traversal(node.left)  # 左
        traversal(node.right)  # 右

    result = []
    traversal(root)  # 调用递归函数
    return result


def inordertraversal(root: Optional[TreeNode]) -> list[int]:
    def traversal(node):
        if not node:  # 递归出口
            return

        traversal(node.left)  # 左
        result.append(node.val)  # 中
        traversal(node.right)  # 右

    result = []
    traversal(root)  # 调用递归函数
    return result


def postordertraversal(root: Optional[TreeNode]) -> list[int]:
    def traversal(node):
        if not node:
            return
        traversal(node.left)  # 左
        traversal(node.right)  # 右
        result.append(node.val)  # 中

    result = []
    traversal(root)  # 调用递归函数
    return result


if __name__ == "__main__":
    # 这里我手动创建一棵树
    tree_list = [1, 2, 3, 4, 5]

    root = TreeNode(tree_list[0])  # 节点1
    node_1 = TreeNode(tree_list[1])  # 节点2
    node_2 = TreeNode(tree_list[2])  # 节点3
    node_3 = TreeNode(tree_list[3])  # 节点4
    node_4 = TreeNode(tree_list[4])  # 节点5

    root.left, root.right = node_1, node_2
    node_1.left, node_1.right = node_3, node_4

    # 前序遍历
    pre_result = preordertraversal(root)
    print("前序遍历结果:", pre_result)

    # 中序遍历
    in_result = inordertraversal(root)
    print("中序遍历结果:", in_result)

    # 前序遍历
    post_result = postordertraversal(root)
    print("后序遍历结果:", post_result)

3.2统一迭代法

 优点:需要的运行空间较少,效率更高。
 缺点:代码多,不易理解。
 统一迭代法:使用统一的思路迭代遍历二叉树迭代法。迭代法最需要注意的地方就是什么时候出栈元素。我们在每个需要出栈并添加到最终的result中的节点后加入一个“None”作为标志,以此来判断出栈的时机,最终实现用统一的思想来书写遍历代码。
代码如下:

from typing import Optional


# 节点类
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val  # 节点的值
        self.left = left  # 节点的左孩子
        self.right = right  # 节点的右孩子


# 前序遍历:中、左、右
def preordertraversal(root: Optional[TreeNode]) -> list[int]:
    if not root:  # 当根节点为空时,直接返回
        return []

    stack = [root]  # 栈结构:保存遍历过程的节点
    result = []  # 最终输出的遍历顺序

    while stack:  # 当栈不为空时,继续遍历
        node = stack.pop()  # 出栈一个节点
        if node:  # 该节点不为空时,加入其孩子节点。由于栈是先进后出,所以要先将右节点入栈,然后是左节点,最后是中间节点
            if node.right:
                stack.append(node.right)  # 右边节点入栈,
            if node.left:
                stack.append(node.left)  # 左边节点入栈
            stack.append(node)  # 中间节点入栈
            stack.append(None)  # 标志:遇见None就说明出栈中间节点了
        else:  # 该节点为空,再出栈一个元素,并将其加入到最终的result中
            node = stack.pop()
            result.append(node.val)

    return result


# 中序遍历:左、中、右
def inordertraversal(root: Optional[TreeNode]) -> list[int]:
    if not root:  # 当根节点为空时,直接返回
        return []

    stack = [root]  # 栈结构:保存遍历过程的节点
    result = []  # 最终输出的遍历顺序

    while stack:  # 当栈不为空时,继续遍历
        node = stack.pop()  # 出栈一个节点
        if node:  # 该节点不为空时,加入其孩子节点。此处是中序遍历,所以要换一下加入栈的顺序。所以要先将右节点入栈,然后是中间节点,最后是左节点。
            if node.right:
                stack.append(node.right)  # 右节点入栈
            stack.append(node)  # 中间节点入栈
            stack.append(None)  # 标志:遇见None就说明出栈中间节点了
            if node.left:
                stack.append(node.left)  # 左结点入栈
        else:  # 该节点为空,再出栈一个元素,并将其加入到最终的result中
            node = stack.pop()
            result.append(node.val)
    return result


# 后序遍历:左、中、右
def postordertraversal(root: Optional[TreeNode]) -> list[int]:
    if not root:  # 当根节点为空时,直接返回
        return []

    stack = [root]  # 栈结构:保存遍历过程的节点
    result = []  # 最终输出的遍历顺序

    while stack:  # 当栈不为空时,继续遍历
        node = stack.pop()  # 出栈一个节点
        if node:  # 该节点不为空时,加入其孩子节点。此处是后序遍历,所以要换一下加入栈的顺序。所以要先将中间节点入栈,然后是右节点,最后是左节点。
            if node.right:
                stack.append(node.right)  # 右节点入栈
            stack.append(node)  # 中间节点入栈
            stack.append(None)  # 标志:遇见None就说明出栈中间节点了
            if node.left:
                stack.append(node.left)  # 左结点入栈
        else:  # 该节点为空,再出栈一个元素,并将其加入到最终的result中
            node = stack.pop()
            result.append(node.val)
    return result


if __name__ == "__main__":
    # 这里我手动创建一棵树
    tree_list = [1, 2, 3, 4, 5]

    root = TreeNode(tree_list[0])  # 节点1
    node_1 = TreeNode(tree_list[1])  # 节点2
    node_2 = TreeNode(tree_list[2])  # 节点3
    node_3 = TreeNode(tree_list[3])  # 节点4
    node_4 = TreeNode(tree_list[4])  # 节点5

    root.left, root.right = node_1, node_2
    node_1.left, node_1.right = node_3, node_4

    # 前序遍历
    pre_result = preordertraversal(root)
    print("前序遍历结果:", pre_result)

    # 中序遍历
    in_result = inordertraversal(root)
    print("中序遍历结果:", in_result)

    # 前序遍历
    post_result = postordertraversal(root)
    print("后序遍历结果:", post_result)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值