L2-012 关于堆的判断

题目:https://www.patest.cn/contests/gplt/L2-012

1.按题目要求先将传进来的数按顺序插入,每插入一个新的元素就要从下向上调整,边插入边调整,不能全部插入后再从上到下调整。

2.得到调整好的堆后,对输入的指令字符串进行分析,取出其中的数字,并判断是题目所给的四类命题的哪一类

   在这里我采用按空格分几个部分输入字符串的形式获取字符串中的数字

   例如输入:

      24 is the root
     26 and 23 are siblings
      46 is the parent of 23
     23 is a child of 10

    先输入第一个数字, 然后判断字符串是否为and ,是就是命题二的形式,则按" %d are siblings",输入即可拿到数字

     如果不是 则判断下一个字符串,如果是"a"则是命题四的形势,按" child of %d"输入拿到数字,以此类推

3.根据坐标位置,判断命题是否正确

   `x is the root ,判断x是不是根节点,与a[0]即可

   `x and y are siblings ,判断x和y是不是兄弟,即判断x和y是否有同一个父亲,关系为:(posX-1)/2 ==(posY-1)/2

   `x is the parent of y ,x是y的父结点,关系为: (posY-1)/2==posX

   `x is a child of y ,x是y的子女,关系为:(posY*2+1)==posX || (posY*2+2)==posX

代码如下:

#include<stdio.h>
#include<string.h>
/*
void siftdown(int a[],int start,int end)
{
	int i=start;
	int j=2*i+1;
	int x=a[i];
	while(j<=end)
	{
		if(j<end&&a[j]>a[j+1])
		{
			j++;
		}
		if(x<=a[j]){
			break;
		}
		a[i]=a[j];
		i=j;
		j=2*i+1;
	}
	a[i]=x;
}
void heapsort(int a[],int start,int end)
{
	int i=0;
	for(i=(end)/2;i>=0;i--)
	{
		siftdown(a,i,end);
	}
}*/
void siftup(int a[],int start)
{
	int i=start;
	int x=a[i];
	int j=(i-1)/2;
	while(i>0){
		if(a[j]>x){
			a[i]=a[j];
		}else{
			break;
		}
		i=j;
		j=(i-1)/2;
	}
	a[i]=x;
}
void find(int a[],int n,int key1,int key2,int* pos1,int* pos2)
{
	*pos1=100+n;
	*pos2=100+n;
	int i=0;
	while(1)
	{
		if(a[i]==key1){
			*pos1=i;
		}
		if(a[i]==key2){
			*pos2=i;
		}
		if(*pos1<n&&*pos2<n){
			break;
		}
		i++;
	}
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	int i;
	int a[100001];
	int pos1,pos2;
	int t; 
	for(i=0;i<n;i++)
	{
		scanf("%d",&t);
		a[i]=t;
		siftup(a,i);//每插入一次,就进行调整 
	}
	//分析输入的命题字符串 
	int j;
	char test[1000];
	getchar();
	for(j=0;j<m;j++)
	{
		char tmp[300];
		int num1;
		int num2;
		scanf("%d",&num1); //第一个一定是数字,先输入,拿到数字一 
		getchar();        //去除掉数字后的第一个空格 
		scanf("%s",tmp);  //输入第二部分的字符串 
		if(strcmp(tmp,"and")==0){//是and,是命题二的形势 
			scanf("%d are siblings",&num2);//拿到数字二 
			find(a,n,num1,num2,&pos1,&pos2); //在数组中遍历找到num1,num2的下标 
			if((pos1-1)/2==(pos2-1)/2){//判断关系输出结果 
	         	 printf("T\n");
	        }else{
	          	printf("F\n");
	        }
		}else{
			getchar();
			scanf("%s",tmp);
			if(strcmp(tmp,"a")==0) //命题四判断是否为父子(前者是后者的子女)的形式 
			{
				scanf(" child of %d",&num2);
				find(a,n,num1,num2,&pos1,&pos2);//在数组中遍历找到num1,num2的下标 
				if(pos2*2+1==pos1||pos2*2+2==pos1)//判断关系输出结果 
		          {
		            printf("T\n");
		          }else{
		            printf("F\n");
		          }
			}else{
				getchar();
				scanf("%s",tmp);
				if(strcmp("root",tmp)==0){
					if(num1==a[0]){    //命题一 判断是否为根结点,与a[0]比较 
			          printf("T\n");
			        }else{
			          printf("F\n");
			        }
				}else{
					scanf(" of %d",&num2); //命题三 判断"子父"(后者是前者的子女)关系即
					find(a,n,num1,num2,&pos1,&pos2);//在数组中遍历找到num1,num2的下标
					if((pos2-1)/2==pos1)//判断关系输出结果
			          {
			            printf("T\n");
			          }else{
			            printf("F\n");
			          }
				}
			}
		}
	}
	return 0;
}
1.这道题其实一开始想不是很复杂,但是由于对堆的排序不熟,有点小差错,加上 阅读题目不仔细,没有边插入边排序,搞了我快一天的时间

2.再者,以后分析输入字符串,就用按空格分段输入,这样容易理解,只要缜密就不会出错。

3.话不多说,我赶紧去把堆排序再码一遍

问题:

1.其实这里我有个疑问,用siftdown()调整和siftup()调整得到的堆会不一样吗?

2.题目所给的值应该都是互不相同的把?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值