九度OJ 1061: 成绩排序

题目描述:

    有N个学生的数据,将学生数据按成绩高低排序,如果成绩相同则按姓名字符的字母序排序,如果姓名的字母序也相同则按照学生的年龄排序,并输出N个学生排序后的信息。

输入:

    测试数据有多组,每组输入第一行有一个整数N(N<=1000),接下来的N行包括N个学生的数据。
    每个学生的数据包括姓名(长度不超过100的字符串)、年龄(整形数)、成绩(小于等于100的正数)。

输出:

    将学生信息按成绩进行排序,成绩相同的则按姓名的字母序进行排序。
    然后输出学生信息,按照如下格式:
    姓名 年龄 成绩

样例输入:
3
abc 20 99
bcd 19 97
bed 20 97
样例输出:
bcd 19 97
bed 20 97
abc 20 99
提示:

学生姓名的字母序区分字母的大小写,如A要比a的字母序靠前(因为A的ASC码比a的ASC码要小)。

来源:

2000年清华大学计算机研究生机试真题


题目分析:


这是清华2000年机试难度相对较大的一题,其他3题都是水题。
本题考察的核心是结构体的排序。
去年暑假的我显得很憨厚,手写了一个compare函数,再手写了一个归并排序函数,很费劲的AC了。
今天用了qsort()排序,大大简化了代码量,提高了效率。
这道题放到今天看来,也就是比水题难度稍大。
关于qsort()及sort()排序和对应的cmp函数,大家可以去百度学习一下。

源代码1(去年的)


#include <iostream>
#include <cstdlib>
#include <cstring>
 
typedef struct {
    char name[102];
    int age;
    int score; 
}student;
 
bool compare(student a, student b)
{
    if(a.score<b.score)
        return 1;
    else if(a.score==b.score)
    {
        int la=strlen(a.name), lb=strlen(b.name);
        int lmin;
        if(la<=lb) lmin = la;
        else lmin = lb;
        int k=0;
        while(k<=lmin)
        {
            if(a.name[k]<b.name[k])
                return 1;
            else if(a.name[k]>b.name[k])
                return 0;
            k++;
        }
        if(a.age<b.age)
            return 1;
    }
    return 0;
}
 
void Merge(student array[], int p, int q, int r)
{
    int i, j, k;
    student* temp = (student*)malloc((r-p+1)*sizeof(student));
    for(i=p,j=q+1,k=0; i<=q && j<=r; k++)
    {
        if(compare(array[i], array[j]))
            temp[k]=array[i++];
        else
            temp[k]=array[j++];
    }
    while(i<=q)
        temp[k++]=array[i++];
    while(j<=r)
        temp[k++]=array[j++];
    for(k=0; k<(r-p+1); k++)
        array[p+k] = temp[k];
    free(temp);
}
 
void MergeSort(student array[], int low, int high)
{
    int mid = 0;
    if(low<high)
    {
        mid = (low+high)/2;
        MergeSort(array, low, mid);
        MergeSort(array, mid+1,high);
        Merge(array, low, mid, high);
    }
}
 
int main()
{
    using namespace std;
    int n;
    while(cin >> n)
    {
        student stu[1001];
        int i;
        for(i=1; i<=n; i++)
            cin >> stu[i].name >> stu[i].age >> stu[i].score;
        MergeSort(stu, 1, n);
        for(i=1; i<=n; i++)
            cout << stu[i].name << " " << stu[i].age << " " << stu[i].score << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1061
    User: superlc320
    Language: C++
    Result: Accepted
    Time:710 ms
    Memory:1556 kb
****************************************************************/

源代码2(今天改进的)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
  
typedef struct student       //定义学生结构体
{
    char name[102];
    int age;
    int score; 
}student;
 
int cmp(const void *a, const void *b)           //qsort()的cmp函数
{
    student* sa=(student*)a;                    //简化后面的代码
    student* sb=(student*)b;
    if(sa->score == sb->score)
    {   
        if(!strcmp(sa->name, sb->name))
            return sa->age - sb->age;           //如果分数相同,名字也相同,则比较年龄
        else
            return strcmp(sa->name, sb->name);    //如果分数相同,名字不同,则比较名字 
    }
    return sa->score - sb->score;               //如果分数不同则比较分数
}
  
int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        student stu[1001];
        int i;
        for(i = 0; i < n; i++)
            scanf("%s%d%d", stu[i].name, &stu[i].age, &stu[i].score);
        qsort(stu, n, sizeof(student), cmp); //运用qsort()或者sort()可以避免手写排序算法
        for(i = 0; i < n; i++)
            printf("%s %d %d\n", stu[i].name, stu[i].age, stu[i].score);
    }
    //system("pause");
    return 0;
}
/**************************************************************
    Problem: 1061
    User: superlc320
    Language: C++
    Result: Accepted
    Time:60 ms
    Memory:1064 kb
****************************************************************/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值