构建二叉搜索树

二叉搜索树 (BST) 递归定义为具有以下属性的二叉树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
  • 若它的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值
  • 它的左、右子树也分别为二叉搜索树

给定二叉树的具体结构以及一系列不同的整数,只有一种方法可以将这些数填充到树中,以使结果树满足 BST 的定义。

请你输出结果树的层序遍历。

示例如图 1 和图 2 所示。

输入格式

第一行包含一个正整数 N,表示树的结点个数。

所有结点的编号为 0∼N−1,并且编号为 0 的结点是根结点。

接下来 N 行,第 i 行(从 0 计数)包含结点 i 的左右子结点编号。如果该结点的某个子结点不存在,则用 −1 表示。

最后一行,包含 N 个不同的整数,表示要插入树中的数值。

输出格式

输出结果树的层序遍历序列。

数据范围

1≤N≤100

输入样例:

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

输出样例:

58 25 82 11 38 67 45 73 42

最近每天都会写2-3道题保持手感,遇到好的题就会上传~ 

分析:之前从来没有系统的写过树的题,感觉像这种二叉搜索树的题应该是有板子的,我是按照自己对这道题的理解,用函数dfs1,求出每一个节点的左子树有几个节点,这个是用来确定该节点应该填哪个数用的 ,因为假设根节点的左子树有5个节点,那我们就可以知道根节点是第6大的数,我们就可以把c[6]赋值给根节点,因此我们还要把输入的c[]数组排一下序,填每个节点的值时,我用了dfs函数,深度遍历填写的,这里需要注意的时,一个节点的左子树有k个节点不代表该节点就填c[k](从0到n-1的下标),这只能说明该节点在以该节点为根节点的树中排第k+1,因此dfs函数还要添加参数ll,rr作为左右范围。最后用一个bfs遍历输出答案,因为要求的是层序遍历结果。

代码如下:

#include <bits/stdc++.h>

using namespace std;
struct node{
int l,r,id;
int w;
}adj[110];
int n,a,b;
int c[101],st[101],al[101];
int dfs1(int id)
{
    int ll=0,rr=0;
    if(adj[id].l) ll = dfs1(adj[id].l);
    if(adj[id].r) rr = dfs1(adj[id].r);
    al[id]=ll;
    return ll+rr+1;
}
void dfs(int id,int ll,int rr)
{
    //cout<<id<<" ";
    int num=al[id];
    adj[id].w=c[num+ll];
    if(adj[id].l) dfs(adj[id].l,ll,num+ll-1);
    if(adj[id].r) dfs(adj[id].r,num+ll+1,rr);
}
void bfs()
{
    queue<int>q;
    q.push(0);
    while(q.size())
    {
        int u=q.front();
        q.pop();
        cout<<adj[u].w<<" ";
        if(adj[u].l)q.push(adj[u].l);
        if(adj[u].r)q.push(adj[u].r);
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a>>b;
        if(a!=-1) adj[i].l=a;
        if(b!=-1) adj[i].r=b;
    }
    for(int i=0;i<n;i++) cin>>c[i];
    dfs1(0);
    sort(c,c+n);
    dfs(0,0,n-1);
    bfs();
    return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值