#1099. Build A Binary Search Tree【树的遍历 + DFS + BFS + 二叉搜索树】

原题链接

Problem Description:

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
  • Both the left and right subtrees must also be binary search trees.

Given the structure of a binary tree and a sequence of distinct integer keys, there is only one way to fill these keys into the tree so that the resulting tree satisfies the definition of a BST. You are supposed to output the level order traversal sequence of that tree. The sample is illustrated by Figure 1 and 2.

在这里插入图片描述

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N N N ( ≤ 100 \leq 100 100) which is the total number of nodes in the tree. The next N N N lines each contains the left and the right children of a node in the format left_index right_index, provided that the nodes are numbered from 0 to N − 1 N−1 N1, and 0 is always the root. If one child is missing, then −1 will represent the NULL child pointer. Finally N N N distinct integer keys are given in the last line.

Output Specification:

For each test case, print in one line the level order traversal sequence of that tree. All the numbers must be separated by a space, with no extra space at the end of the line.

Sample Input:

9
1 6
2 3
-1 -1
-1 4
5 -1
-1 -1
7 -1
-1 8
-1 -1
73 45 11 58 82 25 67 38 42

Sample Output:

58 25 82 11 38 67 45 73 42

Problem Analysis:

首先要明确二叉搜索树的一些性质,通过本题所给的图也可以观察出,如果将所有节点上的值按照树的中序遍历进行排列,得到的序列一定是按照从小到大排序的。

受此启发,我们可以先将整颗树建好,建树方式参考:#1020. Tree Traversals

将所有节点数值读入后,按照从小到大顺序排列好,然后中序遍历整颗树,在遍历到每个不为空的节点时,将该节点的数值依次填入进去。最后用 BFS 层序遍历整颗树,即可得到答案序列。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>

using namespace std;

const int N = 110;

int n; // 树结点个数
int v[N], w[N], cnt1;
int q[N], ans[N], cnt2;
unordered_map<int, int> l, r; // 存储每个点的左右儿子

void dfs(int root)
{
    int left = l[root];
    int right = r[root];

    if (~left) dfs(left);
    w[root] = v[cnt1 ++ ];
    if (~right) dfs(right);
}

void bfs(int root)
{
    int hh = 0, tt = -1;
    ans[cnt2 ++ ] = w[root];
    q[ ++ tt] = root;

    while (hh <= tt)
    {
        auto t = q[hh ++ ];
        int left = l[t], right = r[t];

        if (~left) ans[cnt2 ++ ] = w[left], q[ ++ tt] = left;
        if (~right) ans[cnt2 ++ ] = w[right], q[ ++ tt] = right;
    }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ )
    {
        int left, right;
        cin >> left >> right;
        l[i] = left, r[i] = right;
    }

    for (int i = 0; i < n; i ++ ) cin >> v[i];
    sort(v, v + n);

    dfs(0); // 0为根节点
    bfs(0);

    for (int i = 0; i < cnt2; i ++ ) 
    {
        cout << ans[i];
        if (i != cnt2 - 1) cout << ' ';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值