二叉树の狂欢

Problem Description
给定一棵二叉树,判断其是否是AVL树(平衡二叉树),如果不是AVL树的话,输出”NOT AVL TREE!!!”以及不平衡的结点个数;否则判断其是否是一棵完全二叉树,如果不是完全二叉树的话,输出”NOT COMPLETE TREE!!!” 以及结点个数饱和的最后一层层号(假设根结点层号为1,且第i层的结点个数饱和是指该层的结点个数等于2^(i-1));否则将这棵完全二叉树经过若干次向下调整变成大顶堆,输出”OHHHHH HEAP!!!”以及此过程中将父结点与子结点交换的总次数(每次父结点与子结点交换都算一次,即同一轮向下调整的过程中可能有多次交换)。

Input
每个输入文件中一组数据。

第一行一个正整数N(N<=20),代表二叉树的结点个数(结点编号为1到N)。

第二行按结点编号从小到大的顺序给出N个结点的权值(各结点的权值均小于20且各不相同)。

接下来按结点编号从小到大的顺序给出N行,每行为两个编号,分别代表该结点的左孩子编号和右孩子编号,如果不存在左(右)孩子,那么就用字符’-‘代替。数据保证编号在1到N之间。

Output
分两行按题目描述中的字符串和相应统计结果。

Sample Input
5
1 2 3 4 5
2 3
4 5
- -
- -
- -

Sample Output
OHHHHH HEAP!!!
3

Author
Shoutmon

Source
17浙大考研机试模拟赛

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> nodeval;
int rts[32],n;

bool isAVL=true;
int ubcounts=0;

bool isCBT=true;
int levcnt[32];

int exchange=0;

int A[32];
struct TreeNode
{
    int val;
    int left,right;
    TreeNode(int v=0,int l=0,int r=0):val(v),left(l),right(r){}
}T[32];
int toindex(string str)
{
    if(str[0]=='-') return -1;
    return stoi(str);
}
int solve(int r,int i,int depth)
{
    if(r==-1) return 0;
    int lh=solve(T[r].left,2*i,depth+1);
    int rh=solve(T[r].right,2*i+1,depth+1);
    if(i>n) isCBT=false;
    levcnt[depth]++;
    if(i<=n) A[i]=nodeval[r];
    if(abs(lh-rh)>=2) isAVL=false,ubcounts++;
    return max(lh,rh)+1;
}
void Adjust(int s,int e)
{
    int temp=A[s];
    int parent=s,child;
    while(2*parent<=e)
    {
        child=2*parent;
        if(child<e&&A[child]<A[child+1]) ++child;
        if(temp>A[child]) break;
        A[parent]=A[child];
        parent=child;
        ++exchange;
    }
    A[parent]=temp;
}
int main()
{
    cin>>n;
    nodeval.resize(n+1);
    for(int i=1;i<=n;++i)
        cin>>nodeval[i];
    for(int i=1;i<=n;++i)
    {
        string L,R;
        cin>>L>>R;
        int left=toindex(L),right=toindex(R);
        T[i].left=left;
        T[i].right=right;
        if(left!=-1)rts[left]=1;
        if(right!=-1)rts[right]=1;
    }
    int root=1;
    while(rts[root]==1) ++root;
    solve(root,1,1);
    if(!isAVL)
    {
        cout<<"NOT AVL TREE!!!\n"<<ubcounts<<endl;
        return 0;
    }
    if(!isCBT)
    {
        cout<<"NOT COMPLETE TREE!!!\n";
        int lv=1,nodes=1;
        while(levcnt[lv]==nodes)
        {
            nodes*=2;
            ++lv;
        }
        cout<<lv-1<<endl;
        return 0;
    }
    cout<<"OHHHHH HEAP!!!\n";
    for(int i=n/2;i>=1;--i)
        Adjust(i,n);
    cout<<exchange<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值