树的遍历
一个二叉树,树中每个节点的权值互不相同。
现在给出它的后序遍历和中序遍历,请你输出它的层序遍历。
输入格式
第一行包含整数 N,表示二叉树的节点数。
第二行包含 N 个整数,表示二叉树的后序遍历。
第三行包含 N 个整数,表示二叉树的中序遍历。
输出格式
输出一行 N 个整数,表示二叉树的层序遍历。
数据范围
1 ≤ N ≤ 30
官方并未给出各节点权值的取值范围,为方便起见,在本网站范围取为 1∼N。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
后序:2 3 1 5 7 6 4
中序:1 2 3 4 5 6 7
后序的最后一个是整棵数的根节点. k表示在根在中序中的位置下标
递归创建左右子树
设后序中左子树的右端点为x:x - pl = k - 1 - il --> x = pl + k - 1 - il
l[root] = build(il, k - 1, pl, pl + k - 1 - il)
后序中右子树的左端点为左子树的右端点+1:
r[root] = build(k + 1, ir, pl + k - il, pr - 1)
#include <iostream>
#include <algorithm>
#include <queue>
#include <unordered_map>
using namespace std;
const int N = 40;
int postorder[N], inorder[N]; // 后序序列和中序序列
// l存每个点的左儿子, r存每个点的右儿子, pos存中序遍历中每个值对应的下标
unordered_map<int, int> l, r, pos;
// 建立二叉树(参数是中序区间和后序区间)
int build(int il, int ir, int pl, int pr)
{
int root = postorder[pr]; // 根节点是后序的最后一个
int k = pos[root]; // 找到根节点在中序中的下标k
// 判断左子树存在,递归创建左子树
if (il < k) l[root] = build(il, k - 1, pl, pl + k - 1 - il);
// 判断右子树存在,递归创建右子树
if (ir > k) r[root] = build(k + 1, ir, pl + k - il, pr - 1);
return root;
}
void bfs(int root)
{
queue<int> q;
q.push(root);
while (q.size())
{
auto t = q.front();
q.pop();
cout << t << ' ';
if (l.count(t)) q.push(l[t]);
if (r.count(t)) q.push(r[t]);
}
}
int main()
{
int n; cin >> n;
for (int i = 0; i < n; i ++) cin >> postorder[i];
for (int i = 0; i < n; i ++)
{
cin >> inorder[i];
pos[inorder[i]] = i;
}
int root = build(0, n - 1, 0, n - 1); // 构建二叉树
bfs(root);
return 0;
}