求先序遍历

GitHub跳转原题关系图返回列表

后序末位定根、中序按下标切成左右子树,在两串切片上递归拼出根+左+右即得先序,无需显式建树。

OJ: roj

题目 ID: 3506

难度:普及-

标签:二叉树递归遍历python

创建: 2026-10-02 04:16

更新: 2026-10-06 12:15

题目描述

给定一棵二叉树的中序遍历与后序遍历(结点为互不相同的大写字母,长度 ≤8\le 8),求先序遍历。

输入共两行,第一行为中序遍历,第二行为后序遍历。输出一行先序遍历。

样例:中序 BADC、后序 BDCA,输出 ABCD。

思路

后序最后一个字符是当前子树的根;在中序中找到该根,左边即左子树、右边即右子树。递归输出根、左子树、右子树即得先序。空子树直接返回。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 04:19
# update_at: 2026-10-02 04:19

import sys


def preorder(inorder: str, postorder: str) -> str:
    """由中序 + 后序还原先序:后序末位是根,中序按根切成左右子树递归。"""
    if not postorder:  # 空子树
        return ''
    root = postorder[-1]                       # 后序最后一个一定是子树根
    i = inorder.index(root)                    # 根在中序里的位置 = 左子树大小
    left, right = i, len(inorder) - i - 1
    return root + preorder(inorder[:left], postorder[:left]) \
        + preorder(inorder[left + 1:], postorder[left:left + right])


def solve() -> None:
    data = iter(sys.stdin.read().split())
    inorder, postorder = next(data), next(data)
    print(preorder(inorder, postorder))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-06 12:15
 * update_at: 2026-10-06 12:15
 */
#include <iostream>
#include <string>
using namespace std;

typedef long long ll;

string inorder, postorder;

// 由中序区间 [l1, r1] 与后序区间 [l2, r2] 递归输出先序
void preorder(ll l1, ll r1, ll l2, ll r2) {
    if (l1 > r1 || l2 > r2) return; // 空子树
    char root = postorder[r2];      // 后序末位是根
    cout << root;
    ll i = l1;
    while (i <= r1 && inorder[i] != root) ++i; // 根在中序中的位置
    ll left_size = i - l1;          // 左子树结点个数
    // 左子树:中序 [l1, i-1],后序 [l2, l2+left_size-1]
    preorder(l1, i - 1, l2, l2 + left_size - 1);
    // 右子树:中序 [i+1, r1],后序 [l2+left_size, r2-1]
    preorder(i + 1, r1, l2 + left_size, r2 - 1);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> inorder >> postorder;
    ll n = inorder.size();
    preorder(0, n - 1, 0, n - 1);
    cout << '\n';
    return 0;
}