【Acwing】【蓝桥杯集训】【递归】

树的遍历

一个二叉树,树中每个节点的权值互不相同。

现在给出它的后序遍历和中序遍历,请你输出它的层序遍历。

输入格式

第一行包含整数 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;
}

猜你喜欢

转载自blog.csdn.net/laaa123mmm/article/details/129470274