二叉树遍历:由后序与中序推导层序结果(多语言实现)
题目描述
有一棵二叉树,每个节点由一个大写字母标识 (最多 26 个节点)。 现有两组字母,分别表示后序遍历(左孩子->右孩子->父节点)和中序遍历(左孩子->父节点->右孩子)的结果,请你输出层序遍历的结果。
输入描述
每个输入文件一行,第一个字符串表示后序遍历结果,第二个字符串表示中序遍历结果。(每串只包含大写字母) 中间用单空格分隔。
输出描述
输出仅一行,表示层序遍历的结果,结尾换行。
用例
| 输入 | CBEFDA CBAEDF |
| 输出 | ABDCEF |
| 说明 | 二叉树为: A |
题目解析
二叉树的三种遍历方式:
- 前序遍历:根节点 → 左子树 → 右子树
- 中序遍历:左子树 → 根节点 → 右子树
- 后序遍历:左子树 → 右子树 → 根节点
这三种遍历方式的命名依据是根节点的访问顺序:
- "前"表示根节点最先访问
- "中"表示根节点在中间访问
- "后"表示根节点最后访问
无论哪种遍历方式,左右子树的访问顺序始终保持一致:先左后右。
掌握了二叉树遍历的基本原理后,我们可以进行实际案例分析。给定以下输入数据:
- 后序遍历序列:CBEFDA
- 中序遍历序列:CBAEDF
分析步骤如下:
- 根据后序遍历"左右根"的特性,序列最后一个元素 A 即为整棵树的根节点
- 在中序遍历"左根右"的序列中,根节点 A 将序列分为左右两部分:
- 左子树序列:CB
- 右子树序列:EDF
- 对左右子树重复上述过程:
- 在后序序列中找到子树根节点
- 在中序序列中划分新的左右子树
通过这种递归分解的方式,我们可以逐步构建出完整的二叉树结构。
当所找到的根节点左右子树仅含一个节点或无节点时,即可终止递归过程。 递归完成后即可重建完整树形结构,按照层序遍历规则可直接得出结果:ABDCEF。
值得注意的是,本题看似需要通过深度优先搜索 (DFS) 构建树结构,实则可通过广度优先搜索 (BFS) 策略优化处理。采用 BFS 可直接实现层序遍历效果,无需先构建树结构再进行二次遍历。
BFS 层序遍历的具体实现逻辑如下:
- 根据后序遍历结果定位根节点 A
- 通过中序遍历结果确定根节点 A 的左右子树分布
- 由此可准确获取左右子树的规模信息
通过左右子树的长度,我们可以从后序遍历结果中划分出左子树和右子树部分,并确定它们各自的根节点(即对应部分的最后一个元素)。 在遍历过程中,我们始终优先处理子树的根节点,然后再递归处理其左右子树。
JavaScript 算法源码
/* JavaScript Node ACM 模式 控制台输入获取 */
const readline = require("readline");
const rl = readline.createInterface({
input: process.,
: process.,
});
rl.(, {
[post, mid] = line.();
.((post, mid));
});
() {
queue = [];
ans = [];
(post, mid, queue, ans);
(queue.) {
[post, mid] = queue.();
(post, mid, queue, ans);
}
ans.();
}
() {
rootEle = post.(-);
ans.(rootEle);
rootIdx = mid.(rootEle);
leftLen = rootIdx;
(leftLen > ) {
leftPost = post.(, leftLen);
leftMid = mid.(, rootIdx);
queue.([leftPost, leftMid]);
}
(post. - - leftLen > ) {
rightPost = post.(leftLen, post. - );
rightMid = mid.(rootIdx + );
queue.([rightPost, rightMid]);
}
}

