树的遍历(二叉树)

225 阅读2分钟

L2-006 树的遍历 (pintia.cn)

题目描述

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

题目分析

本题为二叉树的 中序遍历后序遍历 推出 层序遍历

由于本人对数据结构不甚了解,故将此题作题解。

首先考虑后序遍历的性质,即对于一个节点而言,需要先遍历左子树,再遍历右子树,最终回到当前节点,这也就意味着对于当前遍历得到的序列而言,最后一个数是当前树的根节点。

然后考虑中序遍历的性质,其遍历的顺序为左子树,根节点,右子树。结合对后序遍历的分析,我们可以对中序遍历得到的序列按根节点值进行分割,左侧序列为左子树遍历结果,右侧序列为右子树遍历结果。

在当前分析中,可将本次遍历的树的根节点在层序遍历完全二叉树中的相对位置作为参数传递。

接下来依次递归,便可得到最终层序遍历的结果。

注意节点总数为 30,即树的层数最多为 30 层,这也就意味着若我们用数组记录每个节点在完全二叉树中的相对位置,会产生 MLEMLE 或数组越界的报错。于是我们可以将其相对位置和当前值作为 pair 储存。

Accept代码

#include <bits/stdc++.h>

using namespace std;

const int N = 35;
int n;
int l[N], m[N], r[N];
vector<pair<int, int>> v;

void dfs(int l1, int r1, int l2, int r2, int idx)
{
    if (l1 > r1 || l2 > r2) return ;
    int root = r[r1];
    v.push_back({idx, root});
    int k;
    for (int i = l2; i <= r2; i ++)
        if (m[i] == root)
        {
            k = i - l2;
            break;
        }
    dfs(l1, l1 + k - 1, l2, l2 + k - 1, idx * 2 + 1);
    dfs(l1 + k, r1 - 1, l2 + k + 1, r2, idx * 2 + 2);
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> r[i];
    for (int i = 0; i < n; i ++) cin >> m[i];
    dfs(0, n - 1, 0, n - 1, 0);
    sort(v.begin(), v.end());
    for (int i = 0; i < n; i ++) cout << v[i].second << "\n "[i < n - 1];
    return 0;
}