二叉搜索树/堆 笛卡尔树

4-2-二叉搜索树/堆 笛卡尔树 (25分)  

笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字满足优先队列(不妨设为最小堆)的顺序要求,即该结点的K2值比其子树中所有结点的K2值小。给定一棵二叉树,请判断该树是否笛卡尔树。

输入格式:

输入首先给出正整数N(≤1000),为树中结点的个数。随后N行,每行给出一个结点的信息,包括:结点的K1值、K2值、左孩子结点编号、右孩子结点编号。设结点从0~(N-1)顺序编号。若某结点不存在孩子结点,则该位置给出−。

输出格式:

输出YES如果该树是一棵笛卡尔树;否则输出NO

输入样例1:

6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 21 -1 4
15 22 -1 -1
5 35 -1 -1
 

输出样例1:

YES
 

输入样例2:

6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 11 -1 4
15 22 -1 -1
50 35 -1 -1

输出样例2:

NO
 解题思路
树是递归定义的 1.判断该树是不是小顶堆,即每个节点都比他的左右儿子小
设置一个标记flag,如果不成立flag就被标记,然后返回 2.判断一个树是不是二叉搜索树, 二叉搜索树和中序遍历就是绝配 中序遍历完一遍记录下来 然后递增排序一遍 看一下两者是不是完全相同 若不是,标记flag2      
#include<bits/stdc++.h>
using namespace std;
const int mx=2e5+5;
int f[mx],a1[mx],a2[mx],flag,cnt,flag2=1;
struct node{
    int k1,k2,lt,rt;
}q[mx];
void dui(int root){
    if(!flag)return ;
    if(q[root].lt!=-1){
        if(q[q[root].lt].k2<q[root].k2){
            flag=0;
            return;
        }
        dui(q[root].lt);
    }
    if(q[root].rt!=-1){
        if(q[q[root].rt].k2<q[root].k2){
            flag=0;
            return;
        }
        dui(q[root].rt);
    }
}
void zhongxu(int root){
    if(root!=-1){
        zhongxu(q[root].lt);
        a1[cnt]=a2[++cnt]=q[root].k1;
        zhongxu(q[root].rt);
    }
}
int main(){
    flag=1;
    int n;
    scanf("%d",&n);
    for(int i=0;i<=n-1;i++){
        scanf("%d%d%d%d",&q[i].k1,&q[i].k2,&q[i].lt,&q[i].rt);
        if(q[i].lt!=-1)f[q[i].lt]++;
        if(q[i].rt!=-1)f[q[i].rt]++;
    }
    int root;
    for(int i=0;i<=n-1;i++)if(!f[i])root=i;
    dui(root);
    if(!flag){
        printf("NO");
        return 0;
    }
    zhongxu(root);
    sort(a2+1,a2+cnt+1);
    for(int i=1;i<=cnt;i++){
        if(a1[i]!=a2[i]){
            flag2=0;
            break;
        }
    }
    if(flag2)printf("YES");
    else printf("NO");
}

 

 



上一篇:2020中国大学生程序设计竞赛(CCPC) - 网络选拔赛总结


下一篇:多传感器融合详解