天梯赛 L2-012 关于堆的判断 (二叉树)

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

  • “x is the root”:x是根结点;
  • “x and y are siblings”:x和y是兄弟结点;
  • “x is the parent of y”:x是y的父结点;
  • “x is a child of y”:x是y的一个子结点。

输入格式:

每组测试第1行包含2个正整数N(<= 1000)和M(<= 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出“T”,否则输出“F”。

输入样例:

5 4

46 23 26 24 10

24 is the root

26 and 23 are siblings

46 is the parent of 23

23 is a child of 10

输出样例:

F

T

F

T

分析:

所谓小顶堆就是要求对于树中的每一个根节点来说,即小于他的左子树又小于他的右子树。

我们首先要将输入的序列构造成一个小顶堆,在这个构造的过程中应该注意的一点就是不能够在把树构造完成之后再进行调整,而是应该每当插入一个节点的时候就将树的结构调整好,这里应该注意调整的方法,因为如果你调整的方法不一样的话所构造出来的小顶堆的形式也是不一样的,这样对我们后期数据的判断会有很大的影响。

如果是树的形态构造好之后再进行调整的话,我们应该明确一点就是对于叶子节点来书是不需要进行调整的,所以开始调整的点的下标就应该是n=N/2。

void Tiao(int n)
{
	int temp;
	for(int i=n;i>0;i--)//从第一个节点开始往前调整
	{
		int t=i,op=0;
		while( i*2<=N&&op==0)//有左孩子,并且这个节点没有达到平衡状态
		{
			if(i*2<=N)
				if(a[i]>a[i*2])//有左节点且根节点小于左节点
				{
					t=2*i;
				}
			if(i*2+1<=N)
				if(a[t]>a[i*2+1])//有右节点,且右节点小于左节点和根节点中的较小值
				{
					t=2*i+1;
				}
			if(t!=i)//相当于当前的树形式需要进行调整
			{
				temp=a[i];
				a[i]=a[t];
				a[t]=temp;
				i=t;
			}
			else//不用调整的话,就不用再往下了,
			op=1;
		}
	}
}

但是这种调整的方法并不适合我们的题目,题目要求我们每次插入一个节点之后就要进行调整

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
int N,M;
int a[10000];
void just(int n)
{
    int i=n;
    int temp;
    if(i==1)//第一个相当于整个树的根节点,是不用进行调整的 
        return;
    else
    {
        while(i!=1)//插入的当前结点要与他的根结点进行比较 
        {
            if(a[i]<a[i/2])
            {
                temp=a[i];
                a[i]=a[i/2];
                a[i/2]=temp;
                i=i/2;
            }
            else
                break;
        }
    }
}
int main()
{
    scanf("%d%d",&N,&M);
    for(int i=1; i<=N; i++)
    {
        scanf("%d",&a[i]);//每次加入一个节点都要进行调整 
        just(i);
    }
    getchar();
    for(int kk=1; kk<=M; kk++)
    {
        char s[1000];
        string ss;
        gets(s);
        ss=s;
        int op;
        op=ss.find("root");//find()方法是string类型下的方法 ,返回的是找到的第一个字符的下标 
        if(op!=-1)//相当于找到了 
        {
            int mm;
            sscanf(s,"%d",&mm);//输入流,把s的第一个整形数据给mm 
            if(a[1]==mm)//为根节点 
                printf("T
");
            else
                printf("F
");
        }
        else//没有找到 
        {
            op=ss.find("siblings");
            if(op!=-1)
            {
                int mm,nn,n,m;
                char ch1[10];
                sscanf(s,"%d %s %d",&nn,ch1,&mm);
                for(int i=1; i<=N; i++)
                {
                    if(a[i]==nn)
                        n=i;
                    if(a[i]==mm)
                        m=i;
                }
                if(n/2==m/2)
                    printf("T
");
                else
                    printf("F
");
            }
            else
            {
                op=ss.find("parent");
                if(op!=-1)
                {
                    int mm,nn,m,n;
                    char ch1[10];
                    char ch2[10];
                    char ch3[10];
                    char ch4[10];
                    sscanf(s,"%d %s %s %s %s %d",&nn,ch1,ch2,ch3,ch4,&mm);
                    for(int i=1; i<=N; i++)
                    {
                        if(a[i]==nn)
                            n=i;
                        if(a[i]==mm)
                            m=i;
                    }
                    if(n==m/2)
                        printf("T
");
                    else
                        printf("F
");
                }
                else
                {
                    op=ss.find("child");
                    if(op!=-1)
                    {
                        int mm,nn,n,m;
                        char ch1[10];
                        char ch2[10];
                        char ch3[10];
                        char ch4[10];
                        sscanf(s,"%d %s %s %s %s %d",&nn,ch1,ch2,ch3,ch4,&mm);
                        //这里虽然中间的字符串没有用到,也要获取出来,不然没法取到最后一个整形数据 
						for(int i=1; i<=N; i++)
                        {
                            if(a[i]==nn)
                                n=i;
                            if(a[i]==mm)
                                m=i;
                        }
                        if( n/2==m)
                            printf("T
");
                        else
                            printf("F
");
                    }
                }
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cmmdc/p/6729633.html