数据结构与算法题目集(中文) - 7-31 笛卡尔树(25 分)

题目链接:点击打开链接

题目大意:二叉排序树 + 最小堆判定。

解题思路:这个题只要分开判断这个树的 k1 是否符合二叉排序树,k2 是否符合最小堆即可。最小堆的判断就是从根节点开始,看他的左右孩子的 k2 是否都比根节点的 k2 大,如果是则继续递归,否则 flag = 0 退出循环。 
k1 的判断更简单,只要中序遍历一遍 k1 的值,看知否符合从小到大的排序即可。 
其中在找根节点的时候利用 par 数组,将有父亲节点的孩子标记,则最后那个没有标记(没有父亲的)就是根节点了。

AC 代码

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

struct node
{
    int l,r,k1,k2;
}nds[1010];

int par[1010], a[1010], b[1010];
int flag, len;

void init()
{
    flag=1;
    len=0;
    mem(par,0);
}

void jde_BST(int rt)
{
    if(rt!=-1)
    {
        jde_BST(nds[rt].l);
        a[len]=b[len]=nds[rt].k1;
        len++;
        jde_BST(nds[rt].r);
    }
}

void jde_MinHeap(int rt)
{
    if(!flag) return;

    int l,r;
    if(nds[rt].l!=-1)
    {
        l=nds[rt].l;
        if(nds[rt].k2>nds[l].k2)
        {
            flag=0; return;
        }
        jde_MinHeap(l);
    }

    if(nds[rt].r!=-1)
    {
        r=nds[rt].r;
        if(nds[rt].k2>nds[r].k2)
        {
            flag=0; return;
        }
        jde_MinHeap(r);
    }
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        init();
        int k1,k2,l,r;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d%d",&k1,&k2,&l,&r);
            nds[i].k1=k1, nds[i].k2=k2, nds[i].l=l, nds[i].r=r;
            if(l!=-1) par[l]=1;
            if(r!=-1) par[r]=1;
        }

        int rt;
        for(int i=0;i<n;i++) // 找根节点
            if(par[i]==0){ rt=i; break; }

        jde_MinHeap(rt);
        if(!flag){ puts("NO"); continue; }

        jde_BST(rt);
        sort(a,a+len);
        for(int i=0;i<len;i++)
            if(a[i]!=b[i])
            {
                flag=0; break;
            }

        puts(flag?"YES":"NO");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/dream_weave/article/details/81180275