第五次编程题

    今天郑州下雪了,很大,09年的第一场雪。问了问,家里也下雪了,也很大。今年的雪来的可真早。

    这两天在看第五次的编程比赛题:http://www.programfan.com/club/showpost.asp?id=122355&t=o

    这次的冠军是wgkujgg,他用的是哈希表,但我还没学到哈希表,所以我仔细分析了eastcowboy的方法,eastcowboy的算法设计的真的很巧妙,他用的是二叉树,这是他的代码及我给的注释:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
/*#include<assert.h>*/

typedef struct node
{    char name[31];
    int score;
    struct node *left,*right;
}NODE;

NODE *root = NULL;
int nStudent,nCourse,rank,nowscore;

void MakeTree()
{    int i,cmp;
    char buf[31];
    NODE *p,*parent;  /*parent相当于一个中介节点*/
    scanf("%d",&nStudent); /*学生总数*/
    getchar();
    /*单独处理第一个*/
    gets(buf);
    root = malloc(sizeof(NODE));  /*root是根节点*/
    strcpy(root->name,buf);
    root->score = 0;   /*在函数MakeTree中分数都先置为0*/
    root->left = root->right = NULL;  /*左右孩子置空*/
    /*循环处理后续结点*/
    for(i=1;i<nStudent;++i)
    {    gets(buf);
        p = root;
        while( p )
        {    parent = p;  /*p节点此时的地址要放到parent中保存*/
            cmp = strcmp(buf,p->name);
            /*assert(cmp != 0);*/
            if(cmp>0)
                p = p->right; /*名字比原先输入的大的放到右孩子*/
            else    /*否则左孩子*/    
                p = p->left; 虽然你输入名字时没有在意大小之分,但程序仍对它们排序了,这样查找liming的名字时容易
        }
        p = malloc(sizeof(NODE));
        strcpy(p->name,buf);
        p->score = 0;  /*在函数MakeTree中分数都先置为0*/
        p->left = p->right = NULL; /*左右孩子置空*/
        /*cmp = strcmp(p->name,parent->name);*/
        if(cmp>0)
        {    parent->right = p; /*parent就是这样的作用,它保存p节点上一次的地址*/
        }
        else
        {    parent->left = p;
        }
    } for循环结束
    scanf("%d",&nCourse); /*这一步输入考试次数*/
}  /*上面只输入名字,分数都置0*/

int *searchscore(char *name)  /*此函数的作用是找到名字所对应分数的地址*/
{    NODE *p;
    int cmp;
    p = root;
    while(p)
    {   cmp = strcmp(name,p->name);
        if(cmp>0)
            p = p->right;
        else if(cmp<0)
            p = p->left;
        else
            return &(p->score); /*找到名字后返回的他分数的地址*/
    }
    /*assert(1);*/
    return NULL;
}

void PostOrder(NODE *p)  /*此函数搜索的是liming的名次*/
{    if(p->left)
        PostOrder(p->left);
    if(p->right)
        PostOrder(p->right);
    if(p->score > nowscore)
        ++rank;
}

int main()
{    int i,j,temp;
    int *pscore;
    char namebuf[31],c;
    MakeTree(); 
    pscore = searchscore("Li Ming");
    for(i=0;i<nCourse;++i) /*nCcourse是考试次数*/
    {    for(j=0;j<nStudent;++j)
        {    scanf("%d",&temp); /*temp是成绩*/
            getchar();
            gets(namebuf); /*输入名字,后面一行searchscore(namebuf)返回该名字的分数的地址*/
            *(searchscore(namebuf)) += temp; 
        }

  /*先输入所有名字然后输入分数和名字,名字不再放到树中,分数找到名字对应的分数的地址并放入*/
        rank = 1;
        nowscore = *pscore;
        PostOrder(root); /*调用Post0rder函数找到liming的名次*/
        printf("%d\n",rank);
    }
    return 0;
}

这是eastcowboy的方法。而我用的方法就太笨太原始了,一下子定义了50个10000个字节的数组,其实这个题之所以给10000、50这么大的数字就是要你设计出一种高效率的算法,用多少空间分配多少空间,准确来说我的程序是失败的!这是我的代码:

#include <stdio.h>
#include <string.h>
struct node
   { int number;
     char name[30];
    }a[50][10000];

main()
{   int temp1,n,i,j,m,k;
    char ch='#';
    printf("please input the students totals:\n");
    scanf("%d",&n);     /*学生总数*/  
    printf("please input the names:\n");
    for(i=0;i<n;i++)
    scanf("%s",a[0][i].name);
    printf("please input the exam times:\n");
    scanf("%d",&m);     /*考试次数*/
    for(i=0;i<m;i++)
    { printf("please input the %dth student score and name:\n",i+1);
      for(j=0;j<n;j++)
      scanf("%d%s",&a[i][j].number,a[i][j].name);
    }
    while(ch!='q')
    {
    printf("please input the time you want to see:\n");
    scanf("%d",&k);
    k--; /*因为数组中行的下标从0开始,所以你所查找的行比实际行少1*/
    for(j=0;j<n-1;j++) /*用选择法排序*/ 
     { temp1=j;
      for(i=j+1;i<n;i++)
       if(a[k][i].number<a[k][temp1].number)
       temp1=i;
       a[49][9]=a[k][j];
       a[k][j]=a[k][temp1];
       a[k][temp1]=a[49][9];
      }
    printf("The score from small to big is:\n");
     for(i=0;i<n;i++)
    { printf("%d %s||",a[k][i].number,a[k][i].name);
      if(strcmp(a[k][i].name,"liming")==0) 
      m=a[k][i].number; /*此处使用m*/ 
     }
    for(i=0;i<n;i++)
      if(a[k][i].number==m) j=i; /*j已没有用处,此处使用j*/ 
      printf("the mingci is %d \n",n-j);
      ch=getchar(); 
}
    getchar(); 

    return 0;
}
     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值