PTA天梯赛Python专题:树的遍历详解

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

代码实现:

# 定义TreeNode 二叉树类,__init__ 方法初始化val的值
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

# 定义重建二叉树的函数
def build_tree(postorder, inorder):
    if not postorder or not inorder:
        return None

    # 后序遍历的最后一个节点是根节点
    root_val = postorder[-1]
    root = TreeNode(root_val)

    # 在中序遍历中找到根节点的位置
    root_index = inorder.index(root_val)

    # 左子树的中序遍历和后序遍历
    left_inorder = inorder[:root_index]
    left_postorder = postorder[:root_index]

    # 右子树的中序遍历和后序遍历
    right_inorder = inorder[root_index + 1:]
    right_postorder = postorder[root_index:-1]

    # 递归构建左子树和右子树
    root.left = build_tree(left_postorder, left_inorder)
    root.right = build_tree(right_postorder, right_inorder)

    return root

# 层序遍历,广度优先搜索(BFS)
def level_order_traversal(root):
    if not root:
        return []

    result = []
    queue = [root]

    while queue:
        node = queue.pop(0)
        result.append(node.val)

        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)

    return result

# 输入处理
n = int(input().strip())
postorder = list(map(int, input().strip().split()))
inorder = list(map(int, input().strip().split()))

# 重建二叉树
root = build_tree(postorder, inorder)

# 层序遍历
result = level_order_traversal(root)

# 输出结果
print(" ".join(map(str, result)))

相关知识:

一、类的构造方法

  def __init__(self, x),当创建类的实例时,__init__ 方法会被自动调用

二、根据后序中序得到原二叉树

  1. 确定根节点:后序遍历的最后一个元素是 4,所以根节点的值是 4

  2. 在中序遍历中找到根节点的位置:在中序遍历 [1, 2, 3, 4, 5, 6, 7] 中,4 的位置是索引 3

  3. 将中序遍历分为左子树和右子树

  4. 左子树的中序遍历:[1, 2, 3]

  5. 右子树的中序遍历:[5, 6, 7]

  6. 将后序遍历分为左子树和右子树

  7. 左子树的后序遍历:[2, 3, 1](前 3 个元素)

  8. 右子树的后序遍历:[5, 7, 6](从第 4 个元素到倒数第二个元素)

  9. 递归地对左子树和右子树进行上述步骤

  10. 对左子树(后序:[2, 3, 1],中序:[1, 2, 3]):

  11. 根节点是 1

  12. 在中序遍历中,1 的位置是索引 0

  13. 左子树的中序遍历:[](空)

  14. 右子树的中序遍历:[2, 3]

  15. 左子树的后序遍历:[](空)

  16. 右子树的后序遍历:[2, 3]

  17. 递归地对右子树(后序:[2, 3],中序:[2, 3]):

  18. 根节点是 3

  19. 在中序遍历中,3 的位置是索引 1

  20. 左子树的中序遍历:[2]

  21. 右子树的中序遍历:[](空)

  22. 左子树的后序遍历:[2]

  23. 右子树的后序遍历:[](空)

  24. 递归地对左子树(后序:[2],中序:[2]):

  25. 根节点是 2

  26. 在中序遍历中,2 的位置是索引 0

  27. 左子树和右子树都是空

  28. 对右子树(后序:[5, 7, 6],中序:[5, 6, 7]):

  29. 根节点是 6

  30. 在中序遍历中,6 的位置是索引 1

  31. 左子树的中序遍历:[5]

  32. 右子树的中序遍历:[7]

  33. 左子树的后序遍历:[5]

  34. 右子树的后序遍历:[7]

  35. 递归地对左子树(后序:[5],中序:[5]):

  36. 根节点是 5

  37. 在中序遍历中,5 的位置是索引 0

  38. 左子树和右子树都是空

  39. 递归地对右子树(后序:[7],中序:[7]):

  40. 根节点是 7

  41. 在中序遍历中,7 的位置是索引 0

  42. 左子树和右子树都是空

最终得到原来的二叉树如下 

        4
       / \
      1   6
       \ / \
        3 5 7
       /
      2

  三、层序遍历,广度优先搜索(BFS)

初始状态
  • root = TreeNode(4),根节点的值为 4

  • result = [],结果列表为空。

  • queue = [root],队列中只有根节点。

  • 第一次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出根节点 4

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4]

    5. 将子节点加入队列

    6. queue.append(node.left),加入左子节点 1

    7. queue.append(node.right),加入右子节点 6

    8. 队列状态:queue = [1, 6]

    第二次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出节点 1

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4, 1]

    5. 将子节点加入队列

    6. queue.append(node.left),左子节点为空,不加入。

    7. queue.append(node.right),加入右子节点 3

    8. 队列状态:queue = [6, 3]

    第三次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出节点 6

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4, 1, 6]

    5. 将子节点加入队列

    6. queue.append(node.left),加入左子节点 5

    7. queue.append(node.right),加入右子节点 7

    8. 队列状态:queue = [3, 5, 7]

    第四次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出节点 3

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4, 1, 6, 3]

    5. 将子节点加入队列

    6. queue.append(node.left),加入左子节点 2

    7. queue.append(node.right),右子节点为空,不加入。

    8. 队列状态:queue = [5, 7, 2]

    第五次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出节点 5

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4, 1, 6, 3, 5]

    5. 将子节点加入队列

    6. 左右子节点都为空,不加入。

    7. 队列状态:queue = [7, 2]

    第六次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出节点 7

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4, 1, 6, 3, 5, 7]

    5. 将子节点加入队列

    6. 左右子节点都为空,不加入。

    7. 队列状态:queue = [2]

    第七次循环
    1. 从队列中取出节点

    2. node = queue.pop(0),取出节点 2

    3. 将节点值加入结果列表

    4. result.append(node.val)result = [4, 1, 6, 3, 5, 7, 2]

    5. 将子节点加入队列

    6. 左右子节点都为空,不加入。

    7. 队列状态:queue = []

    循环结束
  • 队列为空,循环结束。

  • 返回结果列表:result = [4, 1, 6, 3, 5, 7, 2]

  • 作者:胡同Alley

    物联沃分享整理
    物联沃-IOTWORD物联网 » PTA天梯赛Python专题:树的遍历详解

    发表回复