这个原理确实我写的没有 https://algo.itcharge.cn/05_tree/05_01_tree_basic/ 这个大佬写的好 还是非常建议看看这个大佬写的 我就拿过来整理了一下 毕竟我们是逆向还原的 主要讲解普通二叉树还原部分 这个在CTF中遇到的很少很少

二叉树还原

  • 必须包含中序遍历: 要唯一还原一棵二叉树,中序遍历是必不可少的“分界线”。

    • 可行组合: 前序+中序、后序+中序、层序+中序。
  • 无法唯一还原的情况:

    • 单一序列: 仅有前序、中序或后序均无法还原。
    • 前序+后序: 无法区分左右子树。例外: 只有当树中不存在度为 1 的节点(如满二叉树)时,才能唯一确定。
遍历序列组合能否唯一还原说明
前序 + 中序可以前序确定根,中序确定左右子树范围
中序 + 后序可以后序确定根,中序确定左右子树范围
中序 + 层序可以层序确定根,中序确定左右子树范围
前序 + 后序不能缺少中序信息,无法区分左右子树

代码实现

from typing import Optional

class TreeNode:
    def __init__(self, val: str):
        self.val = val  # 节点存储的字符值
        self.left = None  # 左子树指针
        self.right = None  # 右子树指针

class BinaryTreeReconstructor:

    # --- 【方法 A】: 前序 + 中序 重建 ---
    # 原理:前序首位是根,中序根在中间,以此切分左右区间
    def buildByPreIn(self, preorder: str, inorder: str) -> Optional[TreeNode]:
        if not preorder or not inorder: return None

        root_val = preorder[0]  # 前序第一个是当前根
        root = TreeNode(root_val)
        idx = inorder.find(root_val)  # 在中序中找到根的位置

        # 递归构建左右子树
        root.left = self.buildByPreIn(preorder[1:idx + 1], inorder[:idx])
        root.right = self.buildByPreIn(preorder[idx + 1:], inorder[idx + 1:])
        return root

    # --- 【方法 B】: 中序 + 后序 重建 ---
    # 原理:后序末位是根,中序根在中间,以此切分左右区间
    def buildByInPost(self, inorder: str, postorder: str) -> Optional[TreeNode]:
        if not inorder or not postorder: return None

        root_val = postorder[-1]  # 后序最后一个是当前根
        root = TreeNode(root_val)
        idx = inorder.find(root_val)  # 在中序中找到根的位置

        # 递归构建左右子树
        root.left = self.buildByInPost(inorder[:idx], postorder[:idx])
        root.right = self.buildByInPost(inorder[idx + 1:], postorder[idx:-1])
        return root

    # --- 【方法 C】: 中序 + 层序 重建 ---
    # 原理:层序第一个是根,通过中序确定左右成员,再过滤层序序列
    def buildByInLevel(self, inorder: str, levelorder: str) -> Optional[TreeNode]:
        if not inorder or not levelorder: return None

        root_val = levelorder[0]  # 层序第一个是根
        root = TreeNode(root_val)
        idx = inorder.find(root_val)

        # 提取属于左子树和右子树的字符集
        left_in = inorder[:idx]
        right_in = inorder[idx + 1:]

        # 关键点:保持层序原有的相对顺序,过滤出子序列
        left_level = "".join([c for c in levelorder if c in left_in])
        right_level = "".join([c for c in levelorder if c in right_in])

        root.left = self.buildByInLevel(left_in, left_level)
        root.right = self.buildByInLevel(right_in, right_level)
        return root

    # --- 【方法 D】: 前序 + 后序 构造 (结果不唯一) ---
    # 原理:假定前序第二个值为左根,在后序中定位以确定左子树范围
    def buildByPrePost(self, preorder: str, postorder: str) -> Optional[TreeNode]:
        if not preorder or not postorder: return None

        root = TreeNode(preorder[0])
        if len(preorder) == 1: return root

        left_root_val = preorder[1]  # 假设前序第二个是左子树的根
        idx = postorder.find(left_root_val)  # 在后序中找到该节点

        # 根据 idx 划分区间递归
        root.left = self.buildByPrePost(preorder[1:idx + 2], postorder[:idx + 1])
        root.right = self.buildByPrePost(preorder[idx + 2:], postorder[idx + 1:-1])
        return root

    # --- 【辅助工具】: 将树转换为层序字符串输出 ---
    # 目的是为了验证重建后的结果是否符合预期的 "ABCDE"
    def to_string(self, root: Optional[TreeNode]) -> str:
        if not root: return "Empty"
        res, queue = [], [root]
        while queue:
            node = queue.pop(0)
            if node:
                res.append(node.val)
                if node.left: queue.append(node.left)
                if node.right: queue.append(node.right)
        return "".join(res)


# ==========================================
# 3. 参数调用与验证脚本
# ==========================================
if __name__ == "__main__":
    recon = BinaryTreeReconstructor()

    # 定义测试数据 (对应的树结构:A是根, B是左, C是右, B下挂D、E)
    #      A
    #     / \
    #    B   C
    #   / \
    #  D   E

    pre_data = "ABDE C".replace(" ", "")  # 前序
    in_data = "DBE A C".replace(" ", "")  # 中序
    post_data = "DEB C A".replace(" ", "")  # 后序
    level_data = "ABCDE".replace(" ", "")  # 层序

    # --- 执行四种重建方案 ---
    t1 = recon.buildByPreIn(pre_data, in_data)
    t2 = recon.buildByInPost(in_data, post_data)
    t3 = recon.buildByInLevel(in_data, level_data)
    t4 = recon.buildByPrePost(pre_data, post_data)

    # --- 输出结果 (验证是否都能变回 ABCDE) ---
    print(f"1. 前序+中序 重建后层序输出: {recon.to_string(t1)}")
    print(f"2. 中序+后序 重建后层序输出: {recon.to_string(t2)}")
    print(f"3. 中序+层序 重建后层序输出: {recon.to_string(t3)}")
    print(f"4. 前序+后序 重建后层序输出: {recon.to_string(t4)}")