题目: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.题目所给的值应该都是互不相同的把?