【实验一】线性表及其应用——运动会分数统计

第一部分  实验要求

【问题描述】
参加运动会的 n 个学校编号为 1~n。比赛分成 m 个男子项目和 w 个女子项目,项目编
号分别为 1~m 和 m+1~m+W。由于各项目参加人数差别较大,有些项目取前五名,得分
顺序为 7,5,3,2,1;还有些项目只取前三名,得分顺序为 5,3,2。写一个统计程序产
生各种成绩单和得分报表。
【基本要求】
产生各学校的成绩单,内容包括各校所取得的每项成绩的项目号、名次(成绩)、姓名和
得分;产生团体总分报表,内容包括校号、男子团体总分、女子团体总分和团体总分。
【测试数据】
对于 n=4,m=3,w=2,编号为奇数的项目取前五名,编号为偶数的项目取前三名,设
计一组实例数据。
【实现提示】
可以假设,n≤20,m≤30,w≤20,姓名长度不超过 20 个字符。每个项目结束时,将
其编号、类型符(区分取前五名还是前三名)输入,并按名次顺序输入运动员姓名、校名(和成
绩)。
【选作内容】
允许用户指定某项目采取其他名次取法。

第二部分  实现代码

以下代码使用C++实现。

#include<iostream>
#include<cstring>
#include<cstdlib>
#define Past_Dream super_FW
using namespace std;
typedef struct record{
    int event_num;
    int competitor_rank;
    string competitor_name;
    int competitor_score;
}state_record;
int main(){
    int school_num , boys_event_num , girls_event_num;
    cout << "Please enter the number of participating schools:";
    cin >> school_num;
    cout << "Please enter the number of events for boys:";
    cin >> boys_event_num;
    cout << "Please enter the number of events for girls:";
    cin >> girls_event_num;
    int total_event_num = boys_event_num + girls_event_num;
    state_record report_card[school_num+1][6*total_event_num];
    int p[school_num+1] = {0} , boys_score[school_num+1][2] , girls_score[school_num+1][2] , total_score[school_num+1][2] ;
    for(int i = 1 ; i <= school_num ; i++){
        p[i] = 1;
        boys_score[i][0] = 0;
        boys_score[i][1] = i;
        girls_score[i][0] = 0;
        girls_score[i][1] = i;
        total_score[i][0] = 0;
        total_score[i][1] = i;
    }
    int temp_event_num , temp_type , temp_sch , new_rule_temp;
    int new_rule[1000] = {0};
    string temp_name;
    char input_temp[1024];
    for(int i = 1 ; i <= total_event_num ; i++){
        cout << "Please enter the event number:";
        cin >> temp_event_num;
        cout << "Please enter the event type(1 for classical Top 5 scoring competition, 2 for classical Top 3 scoring competition, 3 for new rule):";
        cin >> temp_type;
        switch (temp_type){
            case 1:
                for(int j = 1 ; j <= 5 ; j++){
                    cout << "Please enter the school number of the rank " << j << " competitor:";
                    cin >> temp_sch;
                    cout << "Please enter the name of the rank " << j << " competitor:";
                    cin >> temp_name;
                    report_card[temp_sch][p[temp_sch]].event_num = temp_event_num;
                    report_card[temp_sch][p[temp_sch]].competitor_name = temp_name;
                    report_card[temp_sch][p[temp_sch]].competitor_rank = j;
                    switch(j){
                        case 1:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 7;
                            total_score[temp_sch][0] += 7;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 7;
                            else girls_score[temp_sch][0] += 7;
                            break;
                        case 2:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 5;
                            total_score[temp_sch][0] += 5;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 5;
                            else girls_score[temp_sch][0] += 5;
                            break;
                        case 3:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 3;
                            total_score[temp_sch][0] += 3;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 3;
                            else girls_score[temp_sch][0] += 3;
                            break;
                        case 4:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 2;
                            total_score[temp_sch][0] += 2;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 2;
                            else girls_score[temp_sch][0] += 2;
                            break;
                        case 5:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 1;
                            total_score[temp_sch][0] += 1;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 1;
                            else girls_score[temp_sch][0] += 1;
                            break;
                        default:
                            cout << "Error, Please contact the administrator." << endl;
                            break;
                    }
                    p[temp_sch]++;
                }
                break;
            case 2:
                for(int j = 1 ; j <= 3 ; j++){
                    cout << "Please enter the school number of the rank " << j << " competitor:";
                    cin >> temp_sch;
                    cout << "Please enter the name of the rank " << j << " competitor:";
                    cin >> temp_name;
                    report_card[temp_sch][p[temp_sch]].event_num = temp_event_num;
                    report_card[temp_sch][p[temp_sch]].competitor_name = temp_name;
                    report_card[temp_sch][p[temp_sch]].competitor_rank = j;
                    switch(j){
                        case 1:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 5;
                            total_score[temp_sch][0] += 5;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 5;
                            else girls_score[temp_sch][0] += 5;
                            break;
                        case 2:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 3;
                            total_score[temp_sch][0] += 3;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 3;
                            else girls_score[temp_sch][0] += 3;
                            break;
                        case 3:
                            report_card[temp_sch][p[temp_sch]].competitor_score = 2;
                            total_score[temp_sch][0] += 2;
                            if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += 2;
                            else girls_score[temp_sch][0] += 2;
                            break;
                        default:
                            cout << "Error, Please contact the administrator." << endl;
                            break;
                    }
                    p[temp_sch]++;
                }
                break;
            case 3:
                cout << "Please enter how many of the top places can score in this competition:" ;
                cin >> new_rule_temp;
                cout << "Please enter the scores for each position in order of ranking.You can separate the two scores with spaces or carriage returns:";
                for(int j = 1 ; j <= new_rule_temp ; j++){
                    cin >> new_rule[j];
                    if(j!= 1 && new_rule[j] > new_rule[j-1]){
                        fgets(input_temp, sizeof(input_temp), stdin);
                        cout << "Are you sure your input is correct? If you confirm, please enter to skip, otherwise, please enter any character and press enter to re-enter this group of data from the first place.";
                        if (fgets(input_temp, sizeof(input_temp), stdin)) {
                            if (input_temp[0] != '\n'){
                                j = 0;
                                cout << "Please enter the scores for each position in order of ranking.You can separate the two scores with spaces or carriage returns:";
                            }    
                        }
                    }
                }
                for(int j = 1 ; j <= new_rule_temp ; j++){
                    cout << "Please enter the school number of the rank " << j << " competitor:";
                    cin >> temp_sch;
                    cout << "Please enter the name of the rank " << j << " competitor:";
                    cin >> temp_name;
                    report_card[temp_sch][p[temp_sch]].event_num = temp_event_num;
                    report_card[temp_sch][p[temp_sch]].competitor_name = temp_name;
                    report_card[temp_sch][p[temp_sch]].competitor_rank = j;
                    report_card[temp_sch][p[temp_sch]].competitor_score = new_rule[j];
                    total_score[temp_sch][0] += new_rule[j];
                    if(temp_event_num <= boys_event_num) boys_score[temp_sch][0] += new_rule[j];
                    else girls_score[temp_sch][0] += new_rule[j];
                    p[temp_sch]++;
                }
                break;
            default:
                cout << "Error, Please check the input." << endl;
                break;
        }
    }
    for(int i = 1 ; i <= school_num ; i++){
        cout << "School " << i << ":\n";
        cout << "Boys team score: " << boys_score[i][0] << "\n";
        cout << "Girls team score: " << girls_score[i][0] << "\n";
        cout << "Total score: " << total_score[i][0] << "\n";
        for(int j = 1 ; j < p[i] ; j++){
            cout << "Event " << report_card[i][j].event_num << " " << report_card[i][j].competitor_name << " " << report_card[i][j].competitor_rank << " " << report_card[i][j].competitor_score << "\n";
        }
        cout << "--------------------------------------------------------" << endl;
    }
    for(int i = 1 ; i <= school_num ; i++){
        for(int j = i + 1 ; j <= school_num ; j++){
            if(boys_score[i][0] < boys_score[j][0]){
                swap(boys_score[i][0], boys_score[j][0]);
                swap(boys_score[i][1], boys_score[j][1]);
            }
            if(girls_score[i][0] < girls_score[j][0]){
                swap(girls_score[i][0], girls_score[j][0]);
                swap(girls_score[i][1], girls_score[j][1]);
            }
            if(total_score[i][0] < total_score[j][0]){
                swap(total_score[i][0], total_score[j][0]);
                swap(total_score[i][1], total_score[j][1]);
            }
        }
    }
    cout << "Boys' ranking:" << endl;
    for(int i = 1 ; i <= school_num ; i++){
        cout << "School " << boys_score[i][1] << " Boys Team: " << boys_score[i][0] << "\n";
    }
    cout << "--------------------------------------------------------" << endl;
    cout << "Girls' ranking:" << endl;
    for(int i = 1 ; i <= school_num ; i++){
        cout << "School " << girls_score[i][1] << " Girls Team: " << girls_score[i][0] << "\n";
    }
    cout << "--------------------------------------------------------" << endl;
    cout << "Total ranking:" << endl;
    for(int i = 1 ; i <= school_num ; i++){
        cout << "School " << total_score[i][1] << " Total: " << total_score[i][0] << "\n";
    }
    cout << "--------------------------------------------------------" << endl;
    return 0;
}

第三部分  实验报告

一、需求分析

本程序的主要任务是根据各个项目的比赛情况,以学校为单位输出比赛情况的记录,并统计每个学校的男子总分、女子总分和团体总分。

输入形式:用户按照屏幕提示选择相应的操作。在数据录入时,按每个项目比赛结束的排名情况,依次输入(项目号、类型符、运动员名字、所在学校)。

异常处理:对没有数据录入的情况能做出相应处理,比如当没有数据录入时,无法执行生成成绩单或报表的操作。

输出形式:依次按照学校的编号输出该校的比赛情况记录,以及按照学校编号输出该校的男子总分、女子总分及团体总分。

程序执行的命令包括:1.数据录入    2.产生成绩单    3.产生报表

二、概要设计

为了实现上述程序功能,我们用顺序表(数组)来表示比赛记录。为此定义一个抽象数据类型List来管理这些记录,并提供一系列基本操作。以下是详细的ADT定义:

ADT List:

数据对象:D = {ai | ai ∈ ElemSet, i = 1, 2, ..., n, n >= 0},其中 `ElemSet` 是所有可能的比赛记录的集合。

数据关系:R1 = {<ai-1, ai> | ai-1, ai ∈ D, i = 2, ..., n}表示线性表中的元素是按顺序排列的。

基本操作:

1. InitList(&L)

  初始条件: 无

  操作结果: 构造一个空的线性表 L。

2. DestroyList(&L)

  初始条件: 线性表已经存在。

  操作结果: 销毁线性表 L。

3. ListEmpty(L)

  初始条件: 线性表已经存在。

  操作结果: 若 L 为空表,则返回 TRUE,否则返回 FALSE。

4. ListLength(L)

  初始条件: 线性表已经存在。

  操作结果: 返回 L 中数据元素的个数。

5. SchoolReport(L, e)

  初始条件: 线性表已经存在。

  操作结果: 输出 L 中学校编号等于 e 的数据元素的(学校编号,项目编号,运动员姓名,比赛成绩),若这样的数据元素不存在则返回值为 0。

6. SchoolScore(L, e)

初始条件: 线性表已经存在。

操作结果: 输出 L 中学校编号等于 e 的数据元素的团体总分、女子团体总分、男子团体总分,若这样的数据元素不存在则返回值为 0。

7. AllSchoolScores(L)

  初始条件: 线性表已经存在。

  操作结果: 输出各个学校的团体总分、女子团体总分、男子团体总分。

8. Append(&L, e)

  初始条件: 线性表已经存在。

  操作结果: 在 L 的末尾插入一个元素 e。

数据结构定义

typedef struct record {
    int event_num;
    int competitor_rank;
    string competitor_name;
    int competitor_sch;  // 学校编号
    int competitor_score;
} state_record;
typedef struct {
    state_record data[MAX_SIZE];
    int size;
} List;

本程序包含三个主要模块:

主程序模块:负责初始化系统,接受用户命令,并根据命令调用相应的处理函数。

顺序表的单元模块:实现顺序表的抽象数据类型(ADT),提供对顺序表的基本操作。

结点结构的单元模块:定义顺序表的结点结构。

各模块之间的调用关系如下:

三、详细设计

1.结点结构的详细定义

typedef struct record{
    int event_num;
    int competitor_rank;
    string competitor_name;
    int competitor_score;
}state_record;

2.顺序表的详细定义及基本操作

state_record结构体用来存储每个参赛者的成绩记录,包含事件编号(event_num)、名次(competitor_rank)、姓名(competitor_name)和分数(competitor_score)。

使用二维数组 report_card 来保存所有学校的成绩记录,数组 p 用于追踪每个学校当前已经录入了多少条记录。

三个二维数组 boys_score, girls_score 和 total_score 分别用于存储每个学校男生、女生和总分的情况。其中,第一维索引代表学校编号,第二维的第一个元素是分数,第二个元素是学校编号。

3.主函数的算法

输入处理:

用户首先需要提供参赛学校的总数、男生项目数和女生项目数

对于每个项目,用户需要指定项目类型(传统前五名计分赛、前三名计分赛或是自定义规则),并依次输入获得各名次的选手及其所在学校的信息。

评分机制:

根据选择的不同项目类型,程序使用相应的计分方式为每位参赛者打分,并更新相关学校的分数。如果选择了自定义规则,则还需要额外输入该规则下每一名次对应的分数值

输出结果:

最终,程序将展示各个学校的男队分数、女队分数和总分,并且列出了每一位参与者的具体成绩。此外,还会根据总分对学校进行排名,并显示排名结果

排序算法:

通过简单的冒泡排序方法对 boys_score, girls_score 和 total_score 进行降序排列,以便于最后打印出正确的排行榜。

4.函数的调用关系图

main() --> 初始化变量和数组 --> 获取用户输入数据 --> 处理每项赛事成绩 --> 输出学校成绩详情 --> 排序并输出排名

四、调试分析

1.算法的时空分析

由于采用顺序表,各种操作的算法时间复杂度基本合理。

时间复杂度分析

1. 初始化变量和数组:时间复杂度:O(n),其中 n 是学校数量。初始化过程中,对每个学校的分数、排名等进行设置。

2. 处理每项赛事成绩:对于每一个赛事(总共有 total_event_num 个赛事):如果是传统前5名计分或前3名计分,需要处理最多5或3个获奖者;如果是自定义计分,需要处理 new_rule_temp 个获奖者。时间复杂度:O(m * k),其中 m 是赛事总数,k 是每次赛事的最大获奖者数量(最大为5)。在最坏情况下,m = total_event_num,k = 5。

3. 输出学校成绩详情:遍历每个学校的记录并输出。时间复杂度:O(n * p),其中 n 是学校数量,p 是每个学校平均记录的数量。假设每个学校平均有 p 条记录。

4. 排序并输出排名:使用冒泡排序对所有学校的总分进行排序。时间复杂度:O(n^2),其中 n 是学校数量。冒泡排序的时间复杂度是 O(n^2)。(如果学校数量较多,可以考虑使用更高效的排序算法(如快速排序或归并排序)来优化性能)

总体时间复杂度  近似为 O(m * k + n^2)。

空间复杂度分析

1. 初始化变量和数组:空间复杂度:O(n + m * n * 6),其中 n 是学校数量,m 是赛事总数。report_card[school_num+1][6*total_event_num] 占用的空间是 O(m * n * 6)。

其他变量如 p, boys_score, girls_score, total_score 等占用的空间是 O(n)。

2. 获取用户输入数据

空间复杂度:O(1)。临时变量存储用户输入的数据。

3. 排序并输出排名

空间复杂度:O(1)。冒泡排序是原地排序算法。

总体空间复杂度 近似为O(m * n * 6)。

2.小结

实验使用顺序表实现,调试基本顺利,没有太大的修改,本人确实得到了一次很好的程序设计训练。然而,实验报告真的很难写。

五、用户手册

1、使用环境

操作系统:Windows, macOS, Linux

编译器:支持 C++11 或更高版本的标准编译器(如 GCC, Clang, MSVC)

输入设备:键盘

输出设备:显示器

2、使用说明

2.1 启动程序

运行程序后,首先会提示用户输入参赛学校的数量、男子项目的数量和女子项目的数量。

2.2 输入赛事信息

对于每一个赛事,程序会依次提示用户输入以下信息:

赛事编号:请输入当前赛事的唯一编号。

赛事类型:

输入 1 表示传统前5名计分比赛。

输入 2 表示传统前3名计分比赛。

输入 3 表示自定义计分比赛。

根据所选的赛事类型,输入获奖者的学校编号和姓名:

如果是传统前5名或前3名计分比赛,程序会要求输入前几名的获奖者信息。

如果是自定义计分比赛,程序会要求输入可以得分的名次数量以及每一名次的分数,然后输入相应名次的获奖者信息。

2.3 查看结果

当所有赛事的成绩都录入完毕后,程序会显示每个学校的详细得分情况,包括男队分数、女队分数和总分。

最后,程序会对所有学校的总分进行排序,并输出最终的排名。

六、测试结果

根据测试数据输入后,得到的结果如图:

七、附录

(附源代码,略)

第四部分  致谢

感谢各位读者的阅读。诚然本实验报告与实现代码还是十分不完善的,作为一次作业就不追求完美了,敬请谅解。

何年何夕 两相执手 蚀骨相思 风侵寒透 仙人近侧 怕倚小楼 金缕为笼 歌乐成囚

去思考,去尝试,去突破,去成长

衷心感谢您的阅读,我们下次再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值