數據結構實訓——成績統計系統


1 課題描述

給出n個學生的m門考試的成績表,每個學生的信息由學號、姓名以及各科成績組成。對學生的考試成績進行有關統計,並打印統計表。

2 問題分析和任務定義

1) 按總分數高低次序,打印出名次表,分數相同的為同一名次;

2) 按名次打印出每個學生的學號、姓名、總分以及各科成績。

3 注意測試邊界數據。

4) 對各科成績設置不同的權值。(附加功能)

3 邏輯設計

1)數據類型:

對於學生所包含的信息,學號使用整數型,姓名使用字符串型,各科成績和總成績還有加權成績使用浮點型。同時設置浮點型數組來存儲各科所占權值的比率,設置整數型數組來存儲每個學生的排名。

struct STU

{

    int id;///學號

    char name[20];///姓名

    float score[20];///成績

    float rsum;///加權后的總分

    float sum;///不加權的總分

}s[110];

float ratios[30];///權值比率

int rerank[100];///學生排名

 

2)抽象數據類型

ADT Stu{

數據對象DD是具有相同特征的數據元素的集合。各數據元素均含有類型相同,可唯一標識數據元素的關鍵字。

數據關系R:數據元素同屬一個集合。

input(int n,int m)

操作結果:輸入n個學生的學號,姓名,m科成績。

quick_sort(int n)

操作結果:n個學生按加權總分進行快速排序。

ranks(int n,int rerank[])  

操作結果:n個學生進行排名,加權總分相同的,獲得相同的名次。

display(int n,int m,int rerank[])

按照排名打印n個學生的學號、姓名、總分和各科分數。

}ADT Stu

 

3)模塊功能:

功能上分為輸入、排序、排名、打印這三大模塊。其中排序模塊中需要使用排序算法給學生按照加權成績排名。排名模塊需要編寫算法實現相同分數排名相同的要求。

 

 

 

4 詳細設計

 

學生信息結構體:

struct STU

{

    int id;///學號

    char name[20];///姓名

    float score[20];///成績

    float rsum;///加權后的總分

    float sum;///不加權的總分

}s[110];

 

<1>輸入函數: void input(int n,int m)   

輸入n個學生的學號,姓名,m科成績。

<2>快速排序函數void quick_sort(int n)

n個學生按加權總分進行快速排序。

<3>相同名次處理:void ranks(int n,int rerank[])  

n個學生進行排名,加權總分相同的,獲得相同的名次。

<4>打印函數void display(int n,int m,int rerank[])

按照排名打印n個學生的學號、姓名、總分和各科分數。

 

 

5程序編碼

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct STU
{
    int id;///學號
    char name[20];///姓名
    float score[20];///成績
    float rsum;///加權后的總分
    float sum;///不加權的總分
}s[110];
int my_cmp(STU a,STU b)
{
    if(a.rsum>=b.rsum)///按照加權后的總分來排序
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
void input(int n,int m)
{
    int i,j;
    printf("請輸入學生的學號、姓名和各科成績\n");
    for(i=0; i<n; i++)
    {
        scanf("%d",&s[i].id);
        scanf(" %s",&s[i].name);
        for(j=0; j<m; j++)
        {
            scanf("%f",&s[i].score[j]);
        }
    }
}
void quick_sort(int n)
{
    sort(s,s+n,my_cmp);///STL庫中的快速排序算法
}
void ranks(int n,int rerank[])
{
    int i,k;
    k=0;
    for(i=0;i<n;i++)
    {
        if(s[i].rsum==s[i-1].rsum)
        {
             rerank[i]=k;
        }
        else
        {
            k++;
            rerank[i]=k;
        }
    }
}
void display(int n,int m,int rerank[])
{
    int i,j;
    printf("依次打印排名、學號、姓名、總分、加權總分和各科分數\n");
    for(i=0; i<n; i++)
    {
        printf("%d ",rerank[i]);
        printf("%d ",s[i].id);
        printf("%s ",s[i].name);
        printf("%.2f ",s[i].sum);
        printf("%.2f ",s[i].rsum);
        for(j=0; j<m; j++)
        {
            printf("%.2f ",s[i].score[j]);
        }
        printf("\n");
    }
}

int main()
{
    int n,m,i,j;
    float ratios[30];
    int rerank[100];
    printf("請輸入學生人數n:\n");
    scanf("%d",&n);
    printf("請輸入考試科目數m:\n");
    scanf("%d",&m);
    printf("請依次輸入各科的權重\n");
    for(i=0; i<m; i++)
    {
        scanf("%f",&ratios[i]);
    }
    input(n,m);
    for(i=0; i<n; i++)///計算加權的總分和非加權的總分
    {
        for(j=0; j<m; j++)
        {
            s[i].rsum+=s[i].score[j]*ratios[j];
            s[i].sum+=s[i].score[j];
        }
    }
    quick_sort(n);
    ranks(n,rerank);
    display(n,m,rerank);
    return 0;
}

 

6 程序調試與測試

 

7 結果分析

該程序中學號定義為整型,姓名定義為字符串型,成績定義為單浮點型並保留兩位有效數字。錯誤輸入會造成亂碼和死循環的產生。該程序主要是基於結構體數組來實現排序和輸出的,因而屬於順序表,遍歷輸出的時間復雜度是O(n),空間復雜度也是O(n)。排序所使用的快速排序時間復雜度是O(nlogn)~O(n^2),空間復雜度是O(logn)~O(n)

8 總結

該程序能夠實現按總分數高低次序打印出名次表分數相同的為同一名次),按名次打印出每個學生的學號、姓名、總分以及各科成績同時還實現了給各科加權獲得加權總分的附加功能。基本達到預期目標,但也存在着一些問題,因為使用的是順序表類型的存儲結構實現了隨機存取,但在擴充空間上有着缺陷。該程序雖然簡單,但卻要從實際出發設計,設計的程序要貼近生活,比如在學校中出現成績相同的學生必然有相同的名次,我們平時看到的成績最多是小數點后兩位等一系列問題,告訴我們寫程序要貼近生活,從實際出發。

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM