XDOJ-472 奥运奖牌榜

博客围绕编写函数AdjustSortTable对奥运奖牌榜重新排序展开。先给出问题描述、输入输出格式及样例,接着分析题干,介绍根据比赛信息为队伍添加奖牌的过程。还补充表排序知识,指出函数排序可使用插入排序,也可根据条件修剪排序以缩短运行时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

题目(有点长,可以跳过看下面的思路)

思路

题干分析

函数主体

知识补充

正式内容

结尾


题目(有点长,可以跳过看下面的思路)

问题描述
  给定多个比赛项目的不同国家和地区代表队运动员成绩,总结奥运奖牌榜。请编写一个函数AdjustSortTable,将奖牌榜按照规定的规则进行重新排序。函数声明如下:
void AdjustSortTable(int aSortTable[],struct medalCountry aMedalCountry[], int iCounter, int iNo, int iMedalType);
返回值:

参数:
AdjustSortTable:输入/输出参数,输入表示待重排数组,输出表示重排序后的数组
aMedalCountry:表示当前奖牌数目刚刚发生变化的代表队
iCounter:表示当前奖牌榜上总共有的代表队数目
iNo:表示当前奖牌数目刚刚发生变化的代表队目前在奖牌榜中的位置序号
iMedalType:表示当前奖牌数目刚刚发生变化的代表队刚刚获得的奖牌类型,其值为GOLDMEDAL(值0)代表金牌,SILVERMEDAL(值1)代表银牌,BRONZEMEDAL(值2)代表铜牌。

注意:函数声明已包含在主程序中,不需要自己定义。只需要提交自定义的函数代码。

主程序如下:

主函数输入格式
  输入的第一行包含一个整数n,表示给出了n个比赛项目的前三名所属代表队信息。
  第二行起的n行给出了n个比赛项目的金银铜牌运动员所属代表队信息,每行包含3个字符a1, a2, a3,表示金银铜牌运动员所属代表队代号,相邻的代号之间用一个空格分隔。
主函数输出格式
  输出优先按照金牌数,金牌数相同的按照银牌数,金银牌数目都相同的按照铜牌数从多到少,金银铜牌都相同的按照代号字母顺序排出的奥运奖牌棒。每个国家输出一行,每行包括名次、代表队代号、金牌数、银牌数、铜牌数信息,每项信息占用3个字符长度。
样例输入
8
A B C
C C A
D B C
A D E
A C F
I G H
A D C
C B F
样例输出
1 A 4 0 1
2 C 2 2 3
3 D 1 2 0
4 I 1 0 0
5 B 0 3 0
6 G 0 1 0
7 F 0 0 2
8 E 0 0 1
9 H 0 0 1
样例说明
  在给出的8个项目中,A有4项拿到了金牌,所以排位第1位;D、I的金牌数相同,按银牌数排序,D在I前;E、H的金银铜牌个数均相同,E的字母顺序在H前,因此E排在前。
评测用例规模与约定
1 ≤ n ≤ 303,每个代表队用一个或两个字母代替,总代表队数小于等于206个。

主函数

#include <stdio.h>
#include <string.h>

struct medalCountry{
    int iPlace;
    char sName[3];
    int iMedalNum[3];
};

enum medalType{ GOLDMEDAL , SILVERMEDAL, BRONZEMEDAL};


void AdjustSortTable(int aSortTable[],struct medalCountry aMedalCountry[], int iCounter, int iNo, int iMedalType);

int main(void)
{
    int n,i,j,counter=0;
    struct medalCountry aMedalCountry[206]={0};
    struct medalCountry *pSMC;
    int aSortTable[206];
    char sNameTmp[3];
    scanf("%d",&n);
    for(i=0; i<n; i++)
    {
        //Gold Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[GOLDMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, GOLDMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[GOLDMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, GOLDMEDAL);
        }

        //Silver Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[SILVERMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, SILVERMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[SILVERMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, SILVERMEDAL);
        }

        //Bronze Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[BRONZEMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, BRONZEMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[BRONZEMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, BRONZEMEDAL);
        }
    }

    for(i=0; i<counter; i++)
    {
        aMedalCountry[aSortTable[i]].iPlace = i;
        pSMC=aMedalCountry+aSortTable[i];
        printf("%3d %3s %3d %3d %3d\n", pSMC->iPlace+1, pSMC->sName, pSMC->iMedalNum[GOLDMEDAL], pSMC->iMedalNum[SILVERMEDAL], pSMC->iMedalNum[BRONZEMEDAL]);
    }

    return 0;
}

思路

题干分析

要写出这个题目,我们不妨先来看看主程序在说什么:
首先,题目要求我们输入n场比赛信息,接着为每位获奖队伍添加相应的奖牌

        //Gold Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[GOLDMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, GOLDMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[GOLDMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, GOLDMEDAL);
        }

由于金银铜的奖牌代码没有很大区别,我们这里仅仅拿金牌举例:
第一个循环里,我们在已知的队伍列表中检查有无该队伍
例如样例中的第一行
A B C
读入 A 后,我们在 iMedalCountry结构数组中找到相应的队伍,所以添加了 A,并且递增 counter,接着使用 AdjustSortTable() 函数进行排序。

函数主体

知识补充

这里我们要先知道一个新的排序 表排序 ,什么是表排序呢?这个排序实际上更多体现的是一种间接排序的概念。我们知道,如果排序一个整形数组,可能直接排序元素会很快,可是,如果我们现在排序的元素是一个很大的结构体呢?这时对其进行排序,我们就不能忽略元素复制移动的时间了,因此表排序应运而生。是不是很熟悉,现在知道函数参数里面的 aSortTable 数组是干什么的了吧?

在表排序里,我们排序的并非元素本身,而是排序他们对应的 “指针”,这个不是我们学的的地址指针,而是一个 数组的下标。具体的内容我这里不做过多结束,感兴趣的同学可以看看下面的博文

间接排序(个人理解)_间接排序是什么意思-CSDN博客

正式内容

说了这么多,其实函数本身排序并不难,我们可以使用插入排序

void AdjustSortTable(int aSortTable[], struct medalCountry aMedalCountry[], int iCounter, int iNo, int iMedalType) {
    for (int i = 1; i < iCounter; i++) {
        int j, tmp = aSortTable[i]; //store the element which is ready for insertion
        for (j = i; j > 0; j--) {
            if (aMedalCountry[tmp].iMedalNum[0] > aMedalCountry[aSortTable[j - 1]].iMedalNum[0])  { //compare gold medals
                aSortTable[j] = aSortTable[j - 1];
            }

            else if (aMedalCountry[tmp].iMedalNum[0] == aMedalCountry[aSortTable[j - 1]].iMedalNum[0]) { //compare sliver medals
                if (aMedalCountry[tmp].iMedalNum[1] > aMedalCountry[aSortTable[j - 1]].iMedalNum[1]) {
                    aSortTable[j] = aSortTable[j - 1];
                }

                else if (aMedalCountry[tmp].iMedalNum[1] == aMedalCountry[aSortTable[j - 1]].iMedalNum[1]) {
                    if (aMedalCountry[tmp].iMedalNum[2] > aMedalCountry[aSortTable[j - 1]].iMedalNum[2]) { // compare bronze medals
                        aSortTable[j] = aSortTable[j - 1];
                    }

                    else if (aMedalCountry[tmp].iMedalNum[2] == aMedalCountry[aSortTable[j - 1]].iMedalNum[2]) {
                        if (strcmp(aMedalCountry[tmp].sName, aMedalCountry[aSortTable[j - 1]].sName) < 0) {
                            aSortTable[j] = aSortTable[j - 1];
                        }
                        else break;  //don't forget break
                    }
                    else break;
                }
                else break;
            }

            else break;
        }
        aSortTable[j] = tmp;
    }
}

要注意里面的条件比较,和 break语句就好,我这里没有使用 iNo 和 iMedalType,直接全部重新排序,当然,我们也可以先判断 iMedalType来对排序进行修剪,可以一定程度上缩短运行时间。这里附上一位大佬的代码,大家可以看看,他事先进行了判断,不过他使用的排序是冒泡排序。

佬的博文
http://t.csdnimg.cn/H4UPf

结语

期末考马上就要来了,大家都有做好准备吗,不过不管结果如何,尽力了就好,白云我呢 ,在这里预祝大家都能考到理想的成绩!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值