数据结构项目设计

目录

项目1:计算机设计大赛赛事统计

一、设计主要要求

【问题描述】

【基本要求】

【设计要求】

【测试数据】

【实现提示】

二.问题分析和任务定义

三.逻辑设计

【运行时存储结构】

【文件中存储格式】

【主要功能函数】

【调用关系图】

【流程图】

四、物理设计

(1)Team类结构

(2)School类结构 

(3)Contest类结构

(4)其他数据结构

(5)文件读写

(6)find函数

(7)print函数

(8)insert函数

(9)界面函数

五、测试数据

 补充

项目2:校园导游咨询

一、设计主要要求

【问题描述】

【基本要求】

【测试数据】

【实现提示】

二、问题分析和任务定义

三、逻辑设计

【存储结构】

【查询景点信息模块】

【查询景点路径模块】

【调用关系图】

【流程图】

四、物理设计

【景点类】

【查询景点信息】

 【查询景点路径】 

【Dijkstra算法】

五、预设数据

【景点地图】

【拓扑图】

项目3:算术表达式求解

一、设计主要要求

【问题描述】

【基本要求】

【测试数据】

【实现提示】

二、问题分析和任务定义

三、逻辑设计

【数据结构】

【主要功能函数】

【函数调用关系】

【流程图】

四、物理设计

【核心算法段】

开发工具

结语


项目1:计算机设计大赛赛事统计

一、设计主要要求

【问题描述】

  参加计算机设计大赛的n个学校编号为1~n,赛事分成m个项目,项目的编号为1~m.比赛获奖按照得分降序,取前三名,写一个统计程序产生各种成绩单和得分报表。

【基本要求】

1)每个比赛项目至少有10支参赛队;每个学校最多有6支队伍参赛;

2)能统计各学校的总分;

3)可以按照学校编号或名称,学校的总分、各项目的总分排序输出;

4)可以按学校编号查询学校某个项目的获奖情况;可以按项目编号查询取得前三名的学校;

5)数据存入文件并能随时查询

【设计要求】

1)输入数据形式和范围:可以输入学校的名称,赛事项目的名称。

2)输出形式:有中文提示,各学校分数为整数

3)界面要求:交互设计要合理,每个功能可以设立菜单,根据提示,可以完成相关功能的要求。

4)存储结构:学生自己根据系统功能要求自己设计,但是赛事相关数据要存储在文件中。

【测试数据】

  要求使用全部合法数据,整体非法数据,局部非法数据。进行程序测试,以保证程序的稳定。

【实现提示】

  假设3<赛事项目数量<=10,学校名称长度不超过20个字符。每个赛事结束时,将其编号、名称输入,并依次输入参赛学校编号、学校名称和成绩。

二.问题分析和任务定义

本程序需要实现的功能有:合理的存储、文件存取、用户界面、增加数据功能、删减修改数据功能、统计各个学校总分功能、可以按照学校总分输出成绩表、按照学校编号查询项目获奖情况。可以分解为以下小模块:

1.学校信息管理
2.赛事信息管理
3.队伍报名管理
4.查看获奖信息
5.总分排行榜
6.获奖排行榜
7.关于本程序
0.保存并退出

层次可以表示如下

void menu();                       //一级界面(主界面)
void manageSchool();               //二级界面1:学校信息管理
void manageContest();              //二级界面2:比赛信息管理
void teamRegistration();           //二级界面3:队伍报名管理
void viewPrize();                  //二级界面4:查询学校获奖信息
void printScoreRank();             //二级界面5:总分排行榜
void printPrizeRank();             //二级界面6:获奖排行榜
void printInformation();           //二级界面7:程序信息

限制条件注意点:赛事项目数量限制、赛事参赛队伍最少数量限制,非法输入处理......

三.逻辑设计

【运行时存储结构】

(1)Team类

ADT Team 
    Data
        编号,属于哪个学校,报名哪个比赛,成绩
    Operation
        Constructor
            初始数据:编号,学校,竞赛
            功能:初始化编号、隶属学校、隶属竞赛,成绩默认为0
        Constructor
            初始数据:编号,学校,竞赛,成绩
            功能:初始化编号、隶属学校、隶属竞赛,成绩
        getScore
            前提条件:无
            输入:无
            功能:访问并返回私有变量成绩的数值
            输出:成绩
            后置条件:无
        getNoble
            前提条件:无
            输入:无
            功能:访问并返回私有变量编号的数值
            输出:编号
            后置条件:无
        getSchool
            前提条件:无
            输入:无
            功能:返回隶属学校的数值
            输出:隶属学校的编号
            后置条件:无
        getContest
            前提条件:无
            输入:无
            功能:返回隶属竞赛的数值
            输出:隶属竞赛的编号
            后置条件:无
        setScore
            前提条件:无
            输入:要设置的成绩
            功能:设置私有变量成绩
            输出:无
            后置条件:无
endADT

(2)School

ADT School {
    Data
        编号,名称,队伍数量,队伍编号数组,总成绩
    Operation
        Constructor
            初始数据:编号,学校名称
            功能:初始化编号、学校名称
        addTeam
            前提条件:队伍未满
            输入:队伍编号
            功能:将该编号的队伍加入学校的队伍数组内,并将队伍数量+1
            输出:无
            后置条件:无
        getNoble
            前提条件:无
            输入:无
            功能:访问并返回私有变量编号的数值
            输出:编号
            后置条件:无
        getName
            前提条件:无
            输入:无
            功能:返回学校的名称
            输出:学校名字
            后置条件:无
        getNum
            前提条件:无
            输入:无
            功能:返回下辖队伍数量
            输出:队伍数量
            后置条件:无
        getNum
            前提条件:下标<队伍数量
            输入:下标
            功能:返回下标对应的队伍编号
            输出:下标的队伍编号
            后置条件:无
        Sum
            前提条件:无
            输入:无
            功能:计算队伍的总分
            输出:无
            后置条件:无
        getSum
            前提条件:已经调用过Sum计算总分
            输入:无
            功能:返回计算好的队伍总分
            输出:总分
            后置条件:无
endADT

(3)Contest类

ADT School {
    Data
        编号,名称,队伍数量,参赛队伍编号数组,是否结束标志
    Operation
        Constructor
            初始数据:编号,竞赛名称
            功能:初始化编号、竞赛名称
        addTeam
            前提条件:无
            输入:队伍编号
            功能:将该编号的队伍加入竞赛的队伍数组内,并将队伍数量+1
            输出:无
            后置条件:无
        getNoble
            前提条件:无
            输入:无
            功能:访问并返回私有变量编号的数值
            输出:编号
            后置条件:无
        getName
            前提条件:无
            输入:无
            功能:返回竞赛的名称
            输出:学校名字
            后置条件:无
        getNum
            前提条件:无
            输入:无
            功能:返回报名参加的队伍数量
            输出:队伍数量
            后置条件:无
        getNum
            前提条件:下标<队伍数量
            输入:下标
            功能:返回下标对应的队伍编号
            输出:下标的队伍编号
            后置条件:无
        rank
            前提条件:已调用过finish函数
            输入:无
            功能:将队伍按照分数进行排序
            输出:无
            后置条件:无
        finish
            前提条件:队伍数>=10,并都已打分
            输入:无
            功能:将比赛状态设置为完成
            输出:无
            后置条件:无
        isFinished
            前提条件:无
            输入:无
            功能:返回比赛是否完成
            输出:比赛完成与否
            后置条件:无
endADT

私有变量:赛事编号、赛事名称、含有队伍数、还有队伍编号(数组)等。

公有函数:构造函数、增加队伍函数、排序函数、输出获奖信息函数等。

(4)teams数组、schools数组、contest数组

用标准容器vector存储,基本逻辑为按照学校编号保持有序(便于插入、查询时减小时间复杂度)

【文件中存储格式】

第一行三个数A,B,C分别表示:学校个数、赛事个数、队伍数量。

接下来A行:编号、校名。

接下来B行:编号、赛事状态(结束与否)、赛事名。

接下来C行:编号、参加赛事编号、隶属学校编号、分数。

【主要功能函数】

int findSchool(int noble){      //功能函数1:寻找学校,返回下标
int findContest(int noble){     //功能函数2:寻找赛事,返回下标
int findTeam(int noble){        //功能函数3:找到编号为noble的队伍在容器中的下标,找不到返回-1
void printContestList(){        //功能函数4:输出比赛列表
int MaxOfTeamNoble(){           //功能函数5:返回队伍编号最大值
void insertTeam(Team x){        //功能函数6:将新的Team对象按照编号大小顺序加入teams
void insertContest(Contest x){  //功能函数7:将新的Contest对象按照编号大小顺序加入contests
void insertSchool(School  x){   //功能函数8:将新的School对象按照编号大小顺序加入schools
void writeToFile(){             //功能函数9:保存数据进入文档
void readFromFile(){            //功能函数10:从文档中读取
void firstUse(){                //功能函数11:首次使用
void manageSchool(){            //二级界面1:学校信息管理
void manageContest(){           //二级界面2:比赛信息管理
...

【调用关系图】

注:在各个函数中都可按需调用功能函数,在图不再列出

【流程图】

四、物理设计

以下列出一些数据结构与功能函数。

(1)Team类结构

class Team {
public:
    Team(int n, int school) {
        this->n = n;
        this->belongToSchool = school;
    }
    Team(int n, int school, int contest) {
        this->n = n;
        belongToContest = contest;
        belongToSchool = school;
        score = 0;
    }
    Team(int n, int school, int contest, int score) {
        this->n = n;
        belongToContest = contest;
        belongToSchool = school;
        this->score = score;
    }
    int getScore() { return score; }
    int getNoble() { return n; }
    int getSchool() { return belongToSchool; }
    int getContest() { return belongToContest; }
    void setScore(int score) {
        this->score = score;
    }
private:
    int score;
    int n;
    int belongToContest;
    int belongToSchool;
};

(2)School类结构 

class School {
public:
    School() {}
    School(int n, char* name) {
        this->n = n;
        this->name = name;
        team = 0;
        for (int i = 0; i < 6; i++) teamNum[i] = 0;
        sumScore = 0;
    }
    void addTeam(int num) {  //加入队伍
        if (team >= 6) {
            cout << "队伍数已满\n";
            return;
        }
        teamNum[team++] = num;
    }
    void Sum();                //求和,可返回分数和,并且将结果储存在sumScore中
    int getSum() {
        return sumScore;
    }
    int getNoble() { return n; }
    string getName() { return name; }
    int getNum() { return team; }
    int getNum(int i) {
        if (i < team) return teamNum[i];
    }
private:
    int n;
    string name;
    int team;
    int teamNum[6];
    int sumScore;
};

(3)Contest类结构

class Contest {
public:
    Contest(int n, char* name) {
        team = 0;
        this->n = n;
        this->name = name;
        finished = false;
    }
    void addTeam(int num) {
        teamNum[team++] = num;
    }
    void finish() { finished = true; }
    bool isFinished() { return finished; }
    void rank() {    //排序
        sort(teamNum, teamNum + team, cmpByScore);
    }
    int getNoble() { return n; }
    string getName() { return name; }
    int getNum() { return team; }
    int getNum(int i) { return teamNum[i]; }
private:
    bool finished;
    int n;
    string name;
    int team;
    int teamNum[N];     //存放参赛队伍
};

(4)其他数据结构

vector<Team> teams;
vector<Contest> contests;
vector<School> schools;
int A,B,C;  //A:学校数量    B:比赛数量      C:队伍数量

(5)文件读写

void writeToFile() {             //功能函数9:保存数据进入文档
    fstream out;
    out.open("data.txt", ios::out | ios::ate);
    out << A << ' ' << B << ' ' << C << '\n';
    for (int i = 0; i < A; i++) {
        out << schools[i].getNoble() << schools[i].getName() << "\n";
    }
    for (int i = 0; i < B; i++) {
        out << contests[i].getNoble() << " " << (int)contests[i].isFinished() << contests[i].getName() << "\n";
    }
    for (int i = 0; i < C; i++) {
        out << teams[i].getNoble() << " " << teams[i].getSchool() << " " << teams[i].getContest() << " " << teams[i].getScore() << "\n";
    }
    out.close();
}
void readFromFile() {            //功能函数10:从文档中读取
    fstream in;
    in.open("data.txt", ios::in);
    in >> A >> B >> C;
    for (int i = 0; i < A; i++) {
        int noble;
        char s[20];
        in >> noble;
        in.getline(s, 20, '\n');
        School x(noble, s);
        insertSchool(x);
    }
    for (int i = 0; i < B; i++) {
        int noble;
        char s[20];
        in >> noble;
        int finished = 0;
        in >> finished;
        in.getline(s, 20, '\n');
        Contest x(noble, s);
        if (finished == 1) x.finish();
        insertContest(x);
    }
    for (int i = 0; i < C; i++) {
        int noble;
        int belongC;
        int belongS;
        int score;
        in >> noble >> belongS >> belongC >> score;
        Team x(noble, belongS, belongC, score);
        insertTeam(x);
        schools[findSchool(belongS)].addTeam(noble);    //调用学校类函数addTeam,将本队加入学校数据中
        contests[findContest(belongC)].addTeam(noble);  //更新竞赛队伍数据
    }
    in.close();
    cout << "读取存档成功!";
}

(6)find函数

int findSchool(int noble) {      //功能函数1:寻找学校,返回下标
    vector<School>::iterator i;
    int location = 0;
    for (i = schools.begin(); i != schools.end(); i++) {
        if (i->getNoble() == noble) return location;
        else if (i->getNoble() > noble) return -1;
        else location++;
    }
    return -1;
}
int findContest(int noble) {     //功能函数2:寻找赛事,返回下标
    vector<Contest>::iterator i;
    int location = 0;
    for (i = contests.begin(); i != contests.end(); i++) {
        if (i->getNoble() == noble) return location;
        else if (i->getNoble() > noble) return -1;
        else location++;
    }
    return -1;
}
int findTeam(int noble) {        //功能函数3:找到编号为noble的队伍在容器中的下标,找不到返回-1
    vector<Team>::iterator i;
    int location = 0;
    for (i = teams.begin(); i != teams.end(); i++) {
        if (i->getNoble() == noble) return location;
        else if (i->getNoble() > noble) return -1;
        else location++;
    }
    return -1;
}

(7)print函数

void printContestList() {        //功能函数4:输出比赛列表
    if (contests.empty()) cout << "当前赛事列表为空!\n";
    vector<Contest>::iterator it;
    for (it = contests.begin(); it != contests.end(); it++) {
        cout << "编号" << it->getNoble() << " " << it->getName() << "\t已报名队伍数量:" << it->getNum() << "\t";
        if (it->isFinished()) cout << "已结束\n";
        else cout << "尚未结束\n";
    }
}
void printSchoolList() {         //功能函数12:输出学校列表
    cout << "当前已有学校:\n";
    vector<School>::iterator it;
    for (it = schools.begin(); it != schools.end(); it++)
        cout << "编号" << it->getNoble() << " " << it->getName() << "\t队伍数量:" << it->getNum() << "\n";
}
void printTeamList() {           //功能函数13:输出队伍列表
    cout << "当前已有队伍" << teams.size() << "支\n";
    vector<Team>::iterator it;
    for (it = teams.begin(); it != teams.end(); it++)
        cout << "编号" << it->getNoble() << " 隶属于" << schools[findSchool(it->getSchool())].getName() << "参加了"<<contests[findContest(it->getContest())].getName()<< endl;
}

(8)insert函数

void insertTeam(Team x) {        //功能函数6:将新的Team对象按照编号大小顺序加入teams
    if (findTeam(x.getNoble()) != -1) {
        cout << "该编号的队伍已经存在";
        return;
    }
    else {
        vector<Team>::iterator i;
        bool flag = false;	//标记是否在中间插入过,如果没有,说明应该插在尾部
        for (i = teams.begin(); i != teams.end(); i++) {
            if (i->getNoble() > x.getNoble()) {	//第一个编号比x更大的,插入在此处之前
                flag = true;	//标记更新
                teams.insert(i, x);	//插入
                break;		//找到了即退出
            }	//中间没有合适位置,直接push_back到尾部
        }
        if (!flag) teams.push_back(x);
    }
}
void insertContest(Contest x) {  //功能函数7:将新的Contest对象按照编号大小顺序加入contests
    if (findContest(x.getNoble()) != -1) {
        cout << "该编号的竞赛已经存在";
        return;
    }
    else {
        vector<Contest>::iterator i;
        bool flag = false;	//标记是否在中间插入过,如果没有,说明应该插在尾部
        for (i = contests.begin(); i != contests.end(); i++) {
            if (i->getNoble() > x.getNoble()) {	//第一个编号比x更大的,插入在此处之前
                flag = true;	//标记更新
                contests.insert(i, x);	//插入
                break;		//找到了即退出
            }
        }
        if (!flag) contests.push_back(x);	//中间没有合适位置,直接push_back到尾部
    }
}
void insertSchool(School  x) {   //功能函数8:将新的School对象按照编号大小顺序加入schools
    if (findSchool(x.getNoble()) != -1) {
        cout << "该编号的学校已经存在";
        return;
    }
    else {
        vector<School>::iterator i;
        bool flag = false;	//标记是否在中间插入过,如果没有,说明应该插在尾部
        for (i = schools.begin(); i != schools.end(); i++) {
            if (i->getNoble() > x.getNoble()) {	//第一个编号比x更大的,插入在此处之前
                flag = true;	//标记更新
                schools.insert(i, x);	//插入
                break;		//找到了即退出
            }
        }
        if (!flag) schools.push_back(x);	//中间没有合适位置,直接push_back到尾部
    }
}

(9)界面函数


void manageSchool() {            //二级界面1:学校信息管理
    char choice;
    while (true) {
        cout << "***********学校信息编辑***********\n";
        cout << "1.输出全部学校信息\n";
        cout << "2.新加入学校信息\n";
        cout << "3.删除学校\n";
        cout << "0.返回\n";
        cin >> choice;
        if (choice == '1') {
            if (schools.empty()) cout << "当前学校列表为空!\n";
            vector<School>::iterator it;
            for (it = schools.begin(); it != schools.end(); it++)
                cout << "编号" << it->getNoble() << " " << it->getName() << " 含有队伍数量:" << it->getNum() << "\n";
        }
        else if (choice == '2') {
            cout << "请输入学校编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findSchool(noble) != -1) cout << "已有该编号的学校,录入失败!\n";
            else if (noble <= 0)
                cout << "必须输入正整数!\n";
            else {
                cout << "请输入学校名称:";
                char s[50];
                cin >> s;
                School newAdd(noble, s);
                A++;
                insertSchool(newAdd);
            }
        }
        else if (choice == '3') {
            cout << "您要删除的学校编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findSchool(noble) == -1) cout << "该学校编号不存在,请重新输入\n";
            else {
                School& del = schools[findSchool(noble)];
                C -= del.getNum();
                for (int i = 0; i < del.getNum(); i++) {
                    cout << "该学校编号为" << del.getNum(i) << "的队伍已被删除\n";
                    teams.erase(teams.begin() + findTeam(del.getNum(i)));
                }
                cout << "编号为:" << noble << "的" << schools[findSchool(noble)].getName() << "已被成功删除!\n";
                schools.erase(schools.begin() + findSchool(noble));
                A--;
            }
        }
        else if (choice == '0') { writeToFile(); break; }
    }
}
void manageContest() {           //二级界面2:比赛信息管理
    char choice;
    while (true) {
        cout << "***********赛事信息编辑***********\n";
        cout << "1.输出全部赛事信息\n";
        cout << "2.新加入赛事\n";
        cout << "3.队伍打分\n";
        cout << "4.查看比赛结果\n";
        cout << "0.返回\n";
        cin >> choice;
        if (choice == '1') {
            printContestList();
        }
        else if (choice == '2') {
            cout << "请输入赛事编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findContest(noble) != -1) cout << "已有该编号的比赛,录入失败!\n";
            else if (noble <= 0)
                cout << "必须输入正整数!\n";
            else {
                cout << "请输入赛事名称:";
                char s[20];
                cin >> s;
                Contest newAdd(noble, s);
                B++;
                insertContest(newAdd);
                cout << "加入成功!\n";
            }
        }
        else if (choice == '3') {
            printContestList();
            cout << "输入要进行打分的比赛编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findContest(noble) == -1) cout << "比赛不存在!\n";
            else {
                Contest& now = contests[findContest(noble)];
                if (now.getNum() < 10) {
                    cout << "报名队伍过少,比赛不能开始\n";
                    continue;
                }
                else if (now.isFinished()) {
                    cout << "该比赛已打分\n";
                    continue;
                }
                for (int i = 0; i < now.getNum(); i++) {
                    Team& nowTeam = teams[findTeam(now.getNum(i))];
                    cout << "请给" << i + 1 << "号队伍(编号" << now.getNum(i) << "," << schools[findSchool(nowTeam.getSchool())].getName() << ")打分:";
                    int score;
                    cin >> score;
                    nowTeam.setScore(score);
                }
                now.finish();
                now.rank();
            }
        }
        else if (choice == '4') {
            printContestList();
            cout << "要查看那一场比赛结果:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findContest(noble) == -1) cout << "比赛不存在!\n";
            else {
                Contest& now = contests[findContest(noble)];
                if (!now.isFinished())
                    cout << "尚未打分,无法查看结果!\n";
                else {
                    now.rank();
                    for (int i = 0; i < now.getNum(); i++) {
                        Team& nowTeam = teams[findTeam(now.getNum(i))];
                        cout << "No." << i + 1 << " " << schools[findSchool(nowTeam.getSchool())].getName() << " 分数:" << nowTeam.getScore() << "\n";
                    }
                }
            }
        }
        else if (choice == '0') { writeToFile(); break; }
    }
}
void teamRegistration() {        //二级界面3:队伍报名管理
    char choice;
    while (true) {
        cout << "***********队伍报名管理***********\n";
        cout << "1.学校批量报名\n";
        cout << "2.新建一支队伍\n";
        cout << "3.查看所有队伍状态\n";
        cout << "0.返回\n";
        cin >> choice;
        if (choice == '1') {
            printSchoolList();
            cout << "请输入学校编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findSchool(noble) == -1) cout << "该编号的学校不存在!\n";
            else {
                School& nowSchool = schools[findSchool(noble)];
                int left = 6 - nowSchool.getNum();
                cout << "要报名的队伍数(剩余容量" << left << "):";
                int num;
                cin >> num;
                if (num > left) {
                    cout << "名额不足!\n";
                    continue;
                }
                else if (num < 0) {
                    cout << "必须输入正整数\n";
                    continue;
                }
                else {
                    printContestList();
                    int i = 0;
                    while (i < num) {
                        cout << "队伍" << i + 1 << "报名的比赛编号:";
                        int test;
                        cin.clear();
                        cin.sync();
                        cin >> test;
                        if (findContest(test) == -1) {
                            cout << "报名的比赛不存在,请重新输入\n";
                            continue;
                        }
                        Contest& nowContest = contests[findContest(test)];
                        Team newTeam(MaxOfTeamNoble() + 1, noble, test);
                        C++; i++;
                        cout << "报名成功!\n";
                        if (nowContest.isFinished()) {
                            cout << "当前比赛已开始,请输入该队伍成绩:";
                            int score;
                            cin.clear();
                            cin.sync();
                            cin >> score;
                            newTeam.setScore(score);
                            nowContest.rank();
                        }
                        insertTeam(newTeam);
                        nowSchool.addTeam(newTeam.getNoble());
                        nowContest.addTeam(newTeam.getNoble());
                    }
                }
            }
        }
        else if (choice == '2') {
            printSchoolList();
            cout << "该队隶属学校:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findSchool(noble) == -1) cout << "该学校不存在!\n";
            else {
                School& nowSchool = schools[findSchool(noble)];
                int left = 6 - nowSchool.getNum();
                if (left == 0) {
                    cout << "该学校队伍已满\n";
                    continue;
                }
                printContestList();
                cout << "报名的比赛编号:";
                int test;
                cin.clear();
                cin.sync();
                cin >> test;
                if (findContest(test) == -1) {
                    cout << "报名的比赛不存在\n";
                    continue;
                }
                Contest& nowContest = contests[findContest(test)];
                Team newTeam(MaxOfTeamNoble() + 1, noble, test);
                C++;
                cout << "报名成功!\n";
                if (nowContest.isFinished()) {
                    cout << "当前比赛已开始,请输入该队伍成绩:";
                    int score;
                    cin.clear();
                    cin.sync();
                    cin >> score;
                    newTeam.setScore(score);
                    nowContest.rank();
                }
                insertTeam(newTeam);
                nowSchool.addTeam(newTeam.getNoble());
                nowContest.addTeam(newTeam.getNoble());
            }
        }
        else if (choice == '3') {
            if (teams.empty())
                cout << "当前队伍为空\n";
            else printTeamList();
        }
        else if (choice == '0') {
            writeToFile();
            return;
        }
    }
}
void viewPrize() {               //二级界面4:查询学校获奖信息
    char choice;
    while (true) {
        cout << "*************获奖查询*************\n";
        cout << "1.查询学校获奖信息\n";
        cout << "2.查询竞赛获奖信息\n";
        cout << "0.退出\n";
        cin >> choice;
        if (choice == '1') {
            printSchoolList();
            cout << "请输入学校编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findSchool(noble) == -1) {
                cout << "该学校不存在\n";
            }
            else {
                School& nowSchool = schools[findSchool(noble)];
                bool isFind = false;
                for (int i = 0; i < nowSchool.getNum(); i++) {  //遍历该学校的每一支队伍
                    Team& nowTeam = teams[findTeam(nowSchool.getNum(i))];
                    Contest& nowContest = contests[findContest(nowTeam.getContest())];
                    nowContest.rank();
                    if (nowContest.isFinished()) {    //查找前三中是否有该队伍
                        int prize=1;
                        int i;
                        for (i = 0; i < 3; i++) {
                            if(i==0) prize=1;
                            else if(teams[findTeam(nowContest.getNum(i))].getScore()!=teams[findTeam(nowContest.getNum(i-1))].getScore())
                                prize=i+1;
                            //考虑到分数一样奖牌也应该一样的情况
                            if (nowContest.getNum(i) == nowTeam.getNoble()) {
                                cout << nowSchool.getName() << "的队伍在编号为" << nowContest.getNoble() << "的" << nowContest.getName() << "比赛中,获得了" << prize << "等奖\n";
                                isFind = true;
                            }
                        }
                        //考虑后续还有分数相平的情况
                        while(teams[findTeam(nowContest.getNum(i))].getScore()==teams[findTeam(nowContest.getNum(i-1))].getScore()&&i<nowContest.getNum()){
                            if (nowContest.getNum(i) == nowTeam.getNoble()) {
                                cout << nowSchool.getName() << "的队伍在编号为" << nowContest.getNoble() << "的" << nowContest.getName() << "比赛中,获得了" << prize << "等奖\n";
                                isFind = true;
                            }
                            i++;
                        }
                    }
                }
                if (!isFind) cout << "无获奖信息\n";
            }
        }
        else if (choice == '2') {
            printContestList();
            cout << "请输入比赛编号:";
            int noble;
            cin.clear();
            cin.ignore();
            cin >> noble;
            if (findContest(noble) == -1) {
                cout << "该比赛不存在\n";
            }
            else {
                Contest& now = contests[findContest(noble)];
                now.rank();
                if (!now.isFinished())
                    cout << "该比赛尚未结束\n";
                else {
                    int prize=1;
                    int i;
                    for (i = 0; i < 3; i++) {
                        if(i==0) prize=1;
                        else if(teams[findTeam(now.getNum(i))].getScore()!=teams[findTeam(now.getNum(i-1))].getScore())
                            prize=i+1;
                        Team& nowTeam = teams[findTeam(now.getNum(i))];
                        cout << prize << "等奖:" << schools[findSchool(nowTeam.getSchool())].getName() << "的队伍(编号" << nowTeam.getNoble() << ") 分数为:" << nowTeam.getScore() << endl;
                    }
                    while(teams[findTeam(now.getNum(i))].getScore()==teams[findTeam(now.getNum(i-1))].getScore()&&i<now.getNum()){
                        Team& nowTeam = teams[findTeam(now.getNum(i))];
                        cout << prize << "等奖:" << schools[findSchool(nowTeam.getSchool())].getName() << "的队伍(编号" << nowTeam.getNoble() << ") 分数为:" << nowTeam.getScore() << endl;
                        i++;
                        }

                }
            }
        }
        else if (choice == '0') {
            writeToFile();
            return;
        }
    }
}
void printScoreRank() {          //二级界面5:总分排行榜
    cout << "************总分排行榜************\n";
    int m = schools.size();
    int* rankList = new int[m];
    for (int i = 0; i < m; i++) {
        rankList[i] = i;
        schools[i].Sum();
    }
    sort(rankList, rankList + m, cmpBySum);
    int prize;
    for (int i = 0; i < m; i++) {
        if(i==0) prize=1;
        else if(schools[rankList[i]].getSum()!=schools[rankList[i-1]].getSum())
            prize=i+1;
        cout << "No." << prize << "\t" << schools[rankList[i]].getName();
        //for (int j = 0; j < 20 - (schools[rankList[i]].getName()).length(); j++) cout <<" ";
        cout << "(" << schools[rankList[i]].getSum() << ")\n";
    }
    delete[] rankList;
}
void printPrizeRank() {          //二级界面6:获奖排行榜
    cout << "************奖牌排行榜************\n";
    cout << "名次\t金\t银\t铜\t编号\t 学校名称\t\n";
    int m = schools.size();
    int* gold = new int[m];
    int* silver = new int[m];
    int* bronze = new int[m];
    for (int i = 0; i < m; i++) gold[i] = silver[i] = bronze[i] = 0;
    int* rankList = new int[m];
    for(int i=0;i<B;i++){
        contests[i].rank();
    }
    for(int i=0;i<A;i++){
        schools[i].Sum();
    }
    for (int i = 0; i < m; i++) {
        School& nowSchool = schools[i];
        for (int j = 0; j < nowSchool.getNum(); j++) {  //遍历该学校的每一支队伍
            Team& nowTeam = teams[findTeam(nowSchool.getNum(j))];
            Contest& nowContest = contests[findContest(nowTeam.getContest())];
            if (nowContest.isFinished()) {    //查找前三中是否有该队伍
                if (nowContest.getNum(0) == nowTeam.getNoble()){
                    gold[i]++;
                }
                if (nowContest.getNum(1) == nowTeam.getNoble())
                    silver[i]++;
                if (nowContest.getNum(2) == nowTeam.getNoble())
                    bronze[i]++;
            }
        }
        rankList[i] = i;
    }
    for (int i = 0; i < m - 1; i++)
        for (int j = i + 1; j < m; j++) {
            bool swap = false;
            if (gold[rankList[i]] < gold[rankList[j]])
                swap = true;
            else if (gold[rankList[i]] == gold[rankList[j]])
                if (silver[rankList[i]] < silver[rankList[j]])
                    swap = true;
                else if (silver[rankList[i]] == silver[rankList[j]])
                    if (bronze[rankList[i]] < bronze[rankList[j]])
                        swap = true;
                    else if(bronze[rankList[i]] == bronze[rankList[j]])
                        if(schools[rankList[i]].getSum()<schools[rankList[j]].getSum())
                            swap=true;
            if (swap) {
                int t = rankList[i];
                rankList[i] = rankList[j];
                rankList[j] = t;
            }
        }
    for (int i = 0; i < m; i++) {
        cout << "No." << i + 1 << "\t"<<gold[rankList[i]] << "\t" << silver[rankList[i]] << "\t" << bronze[rankList[i]];
        cout << "\t" << schools[rankList[i]].getNoble() << "\t" << schools[rankList[i]].getName()<<"\n";
    }
    delete[] gold;
    delete[] silver;
    delete[] bronze;
    delete[] rankList;
}
void printInformation() {        //二级界面7:程序信息
    cout << "************程序版本信息************\n";
    cout << "此程序为Jayden Wang 独立自主设计\n";
    cout << "用作数据结构项目设计\n";
    cout << "更新日志:\n2022.5.17    程序框架搭建完成\n";
    cout << "2022.5.19    发布 Vision 1.0.0 Beta.\n";
    cout << "2022.5.19晚   v1.1.0 \n\t修复了mac端输出成绩表时出现死循环的问题;修复了每读一次文档,学校与比赛名称前多一个空格的问题。\n ";
    cout << "2022.5.19晚   v1.1.1\n\t修复了模块5输出不正确的bug,输出了模块6输出不正确的bug\n";
    cout << "2022.5.24     v1.1.2\n\t修复了在查询学校获奖信息时,因为未调用排序rank()算法而产生的错误\n";
    cout << "2022.5.25     v1.2.1\n\t界面美化、加入了新功能:并列学校相同奖项算法,例如:如果有两个第一名,则奖项分别为1 1 3等奖,如果第三名与第四名分数相同,则奖项为1 2 3 3,以此类推\n";
}
void menu() {                    //一级界面(主界面)
    cout << "*********欢迎使用管理系统*********\n";
    fstream file;
    file.open("data.txt", ios::in);
    if (!file.is_open()) {
        cout << "未找到数据文件,本次为首次使用,请根据提示录入数据.\n";
        file.close();
        firstUse();
    }
    else {
        cout << "已找到存档\n";
        file.close();
        readFromFile();
    }
    char choice = ' ';
    while (choice != 7) {
        cout << "\n**************操作****************\n";
        cout << "1.学校信息管理\n";
        cout << "2.赛事信息管理\n";
        cout << "3.队伍报名管理\n";
        cout << "4.查看获奖信息\n";
        cout << "5.总分排行榜\n";
        cout << "6.获奖排行榜\n";
        cout << "7.关于本程序\n";
        cout << "0.保存并退出\n";
        cin >> choice;
        switch (choice) {
        case '1':manageSchool(); break;
        case '2':manageContest(); break;
        case '3':teamRegistration(); break;
        case '4':viewPrize(); break;
        case '5':printScoreRank(); break;
        case '6':printPrizeRank(); break;
        case '7':printInformation(); break;
        case '0':writeToFile(); return;
        default:break;
        }
    }
}

五、测试数据

data.txt储存示例(数据为随意编造,与对应大学实际水平无关)

8 4 44           //A,B,C
1 江苏科技大学    //参赛学校数据
2 苏州科技大学
3 江苏大学
4 浙江大学
5 北京大学
6 清华大学   
7 中国科学技术大学
8 武汉大学
1 1 C++          //比赛项目数据
2 1 JAVA
3 1 PYTHON
4 0 C#
1 1 1 90         //队伍数据
2 1 2 99
3 1 3 98
4 1 4 0
5 2 3 95
6 2 1 80
7 3 1 79
8 3 1 69
9 3 1 88
10 3 1 91
11 3 1 92
12 4 1 95
13 4 1 91
14 4 2 98
15 4 2 96
16 4 2 94
17 4 3 92
18 2 1 24
19 2 1 99
20 2 2 92
21 1 2 88
22 1 3 94
23 5 2 89
24 5 3 100
25 5 2 92
26 5 3 92
27 5 2 94
28 5 4 0
29 6 2 99
30 6 3 93
31 7 3 97
32 7 4 0
33 7 4 0
34 7 4 0
35 7 4 0
36 7 3 10
37 8 4 0
38 8 3 99
39 8 4 0
40 8 4 0
41 6 4 0
42 6 4 0
43 6 2 100
44 8 3 8

 补充

本程序得益于开始的精心数据结构设计,预留了很多升级空间:比如单个修改删除队伍数据、删除学校包括其下辖队伍(这个其实已经做了,做完了才发现没有要求),删除比赛以及内含队伍,来达到更逼真地模仿一般的管理系统;本程序的寻址通过find函数实现,插入使用insert函数实现,与单纯的数组下标寻址相比,对于编号的连续性其实没有依赖,也不需要事先规定学校比赛数量

        ——但是笔者是在是太忙碌着对付期末考试(lan)了,所以......这样也够用了。


项目2:校园导游咨询

一、设计主要要求

【问题描述】

设计一个校园导游程序,为来访的客人提供各种信息查询服务。

【基本要求】

(1) 设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息。

  (2)  为来访客人提供图中任意景点相关信息的查询。

(3) 为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径。

【测试数据】

以江苏科技大学长山校区为例。

【实现提示】

一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向网.顶点和边均含有相关信息.

二、问题分析和任务定义

(1)设计地图:地图标点,并编写景点相关信息,便于旅客查询。

(2)设计存储:用无向图,将景点存放,并设计各个结点之间的拓扑图。

(3)设计算法:使用Dijkstra算法计算最短路径。

限制条件:景点数量>=10

三、逻辑设计

【存储结构】

(1)无向图存储路径信息(拓扑图见预设数据)

#define M 999
int Map[N][N] = {
{M,100,M,200,M,M,M,M,M,M},
{100,M,80,150,M,M,M,M,M,M},
{M,80,M,M,120,110,M,M,M,M},
{200,150,M,M,50,M,M,M,M,M},
{M,M,120,50,M,M,150,230,M},
{M,M,110,M,M,M,80,60,M,M},
{M,M,M,M,M,80,M,M,M,100},
{M,M,M,M,150,60,M,M,90,70},
{M,M,M,M,230,M,M,90,M,50},
{M,M,M,M,M,M,100,70,50,M}
};

(2)景点类ScenicSpot

ADT ScenicSpot{
    Data
        编号
        景点名称
        景点介绍
    Operation
        Constructor
            初始数值:编号、名称、介绍
            功能:初始化对象的上述内容
        print
            前置条件:无
            输入:无
            功能:表格状输出列表编号与名称
            输出:列表编号与名称
            后置条件:无
        printIntroduce
            前置条件:无
            输入:无
            功能:输出景点介绍
            输出:景点介绍
            后置条件:无
end ADT

(3)景点容器

vector<ScenicSpot> SpotList;

(4)路径数组

int path[N];

【查询景点信息模块】

void query():简单的询问信息功能

【查询景点路径模块】

void findPath():询问功能,返回最短路径功能,输出路径功能

int Dijkstra():Dijkstra最短路算法

【调用关系图】

【流程图】

四、物理设计

【景点类】

class ScenicSpot {
public:
    ScenicSpot(int noble, string name, string introduce) { //构造函数
        this->noble = noble;
        this->name = name;
        this->introduce = introduce;
    }
    void print() {   //用于表格状输出列表总体信息
        cout << noble << "\t" << name << "\n";
    }
    void printIntroduce() {//输出景点介绍
        cout << introduce << endl;
    }
private:
    int noble;
    string name;
    string introduce;
};

【查询景点信息】

void query() {
    cout << "你要查询的景点编号(1-10):";
    int n;
    cin >> n;
    if (n < 1 || n>10) {
        cout << "输入不合法!\n";
        return;
    }
    SpotList[n - 1].print();
    SpotList[n - 1].printIntroduce();
}

 【查询景点路径】 

void findPath() {
    cout << "你要查询从哪个景点到哪个景点的最短路径:";
    int a, b;
    cin >> a >> b;
    if (a >= 1 && a <= 10 && b >= 1 && b <= 10) {
        cout << "最短路径长度为" << Dijkstra(a, b) << "\n";
        stack<int> way;
        int nowAt = b - 1;
        while (nowAt != -1) {
            way.push(nowAt + 1);
            nowAt = path[nowAt];
        }
        cout << "最优路径为:";
        while (!way.empty()) {
            cout << way.top();
            if (way.top() != b) cout << "->";
            way.pop();
        }
        cout << '\n';
    }
    else {
        cout << "输入不合法!\n";
    }
}

【Dijkstra算法】

int Dijkstra(int A, int B) {
    int a, b;
    a = A - 1;  b = B - 1;
    bool visited[N];        //用来记录
    int dist[N];
    for (int i = 0; i < N; i++) {
        dist[i] = Map[i][a];  //
        visited[i] = false;       //标记为未访问
        if (i == a) path[i] = -1;
        else if (Map[i][a] == M) path[i] = -1;
        else path[i] = a;
    }
    dist[a] = 0; visited[a] = true; path[a] = -1;    //初始化
    int hasVisited = 1;
    while (hasVisited < N) {
        int min, minLen = M;
        for (int i = 0; i < N; i++)
            if ((!visited[i]) && (dist[i] < minLen)) {
                min = i; minLen = dist[i];
            }
        visited[min] = true;
        hasVisited++;
        for (int i = 0; i < N; i++)
            if (dist[i] > dist[min] + Map[min][i]) {
                dist[i] = dist[min] + Map[min][i];
                path[i] = min;
            }
    }
    return dist[b];
}

五、预设数据

【景点地图】

景点列表
景点编号景点名称
1三号组团
2西苑食堂
3明德园
4文体中心
5西操场
6文理大楼
7北苑
8求索园
9东苑食堂
10图书馆

【拓扑图】

注:数据不与现实吻合


项目3:算术表达式求解

一、设计主要要求

【问题描述】

设计一个简单的算术表达式计算器。

【基本要求】

 实现标准整数类型的四则运算表达式的求值(包含括号,可多层嵌入).

【测试数据】

(30+2*70)/3-12*3

 5+(9*(62-37)+15)*6

 要求自行设计非法表达式,进行程序测试,以保证程序的稳定运行。

【实现提示】

可以设计以下辅助函数

status isNumber(char ReadInChar);  //视ReadInchar 是否是数字而返回 TRUE或 FALSE 。

int TurnToInteger(char IntChar);   // 将字符’0’.’9’ 转换为整数 9

二、问题分析和任务定义

可以实现合法算式的运算。

考虑优先级问题,()内优先,其次*/,最次+-。

采用符号栈存储运算符,用数据栈存储已运算的数据。

可以识别非法算是并给出提示。

注意点:谨慎考虑符号重复出现时的情况、处理结束符号问题、处理第一个元素加入栈时的判断。

三、逻辑设计

【数据结构】

(1)优先级矩阵

//优先级矩阵 1表示优先级更高,0表示优先级更低,2表示括号相遇,-1表示不合法
//0~5 表示 (+-*/)
int priority[6][6] = {
{0,0,0,0,0,2},
{0,1,1,0,0,1},
{0,1,1,0,0,1},
{0,1,1,1,1,1},
{0,1,1,1,1,1},
{-1,1,1,1,1,1}
};

(2)数据栈和符号栈

stack<double> values;   //存放运算数
stack<char> operators;  //存放运算符

【主要功能函数】

int turnToNum(char c):将符号转变成对应的数字编号,非法符号返回-1

int compare(char a, char b):比较符号a和符号b的优先级

bool isNumber(char c):判断是否为数字

double result(double a, char c, double b):产生运算结果

【函数调用关系】

【流程图】

四、物理设计

【核心算法段】

        for (int i = 0; i < (int)strlen(expression); i++) {
            char &c = expression[i];  //c为引用当前字符
            if (isNumber(c)) { num = num * 10 + c - '0'; }
            else if (c == ' ') continue;
            else if (turnToNum(c) != -1) {
                if (c != '(') {
                    int pre = i - 1;
                    while (expression[pre] == ' ') pre--;
                    if (expression[pre] != ')') {
                        values.push((double)num);
                        if(show)cout << "压入" << num << "\n";
                        num = 0;
                    }
                }
                if (c == '=') break;
                if (operators.empty()) {
                    if (show) cout << "压入" << c << "\n";
                    operators.push(c);
                }
                else {
                    bool goOn = true; //标记是否要继续
                    double a, b, r;        //a,b分别存放数字栈最上面的两个数字,c存放运算结果
                    while (!operators.empty() && goOn) {
                        char cTop = operators.top();
                        switch (compare(cTop, c)) {
                        case 1: //栈顶优先级比当前大,消耗栈顶操作符,并计算
                            operators.pop();
                            if (show) cout << "弹出" << cTop << "\n";
                            b = values.top(); values.pop();
                            if (show)cout << "弹出" << b << "\n";
                            a = values.top(); values.pop();

                            if (show)cout << "弹出" << a << "\n";
                            r = result(a, cTop, b);
                            values.push(r);
                            if (show)cout << "压入" << r << "\n";
                            break;
                        case 0: //栈顶优先级比当前小,将当前符号压入
                            operators.push(c);
                            if (show)cout << "压入" << c << "\n";
                            goOn = false;
                            break;
                        case 2: //特殊的,当括号相遇,仅做弹出括号操作
                            if (show)cout << "弹出" << cTop << "\n";
                            operators.pop();
                            goOn = false;
                            break;
                        }
                    }
                    if (operators.empty() && goOn) {
                        operators.push(c);
                        if (show)cout << "压入" << c << "\n";
                    }
                }
            }
            else {
                cout << "该算式非法\n";
                continue;
            }
        }
        
        while (!operators.empty()) {
            int a, b, c;
            char cTop = operators.top();
            operators.pop();
            b = values.top(); values.pop();
            a = values.top(); values.pop();
            c = result(a, cTop, b);
            values.push(c);
        }
        cout << "Answer is " << values.top() << endl;

 补充:这个算法很基础......也找不到什么特别能体现水平的点......优化了一下报错机制,处理了一下开头负数(如-1*3这样的算式)。如果有两个符号中间没有数字的情况,程序会认为中间的数字为0(如1+*2等价为1+0*2答案为1,而非报错),姑且算是机制而不是bug吧^ ^

补充2:本程序设计了开发者模式(输入&开启),打开后将显示栈中元素每一次的压入和弹出情况,便于观察内部运行的逻辑(笔者修改bug时就一直使用的是这个方法)。


开发工具

Windows端(笔者的台式机):Microsoft Visual Studio 2019

Mac端(笔者的笔记本):Microsoft Visual Studio Code


结语

感谢观看!

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
数据结构程序设计项目是指使用数据结构和算法来解决特定问题的项目。这些项目通常涉及设计和实现不同的数据结构,如数组、链表、栈、队列、树等,并使用适当的算法来对这些数据结构进行操作和处理。这些项目要求学生在理解和运用数据结构的基础上,通过编写程序来解决实际的计算机科学问题。 引用中提到,数据结构程序设计项目可以通过真实的案例研究和可重用的软件开发来加深理解。书中还提供了大量的实例和习题,帮助读者理解算法的实质和编程思想。这些项目可以作为高等学校计算机及相关专业课程的一部分。 引用中提供了一个复杂度为O(nlogn)的快速排序程序作为项目3的程序2的示例。这个程序使用快速排序算法对给定的数据进行排序。程序中利用文件读取数据,并计算排序所需的运行时间。 引用中提到了项目3的体验复杂度部分,其中提供了两种排序算法的程序示例,并使用近10万条数据作为输入数据进行运行时间统计。这个项目旨在让学生感受到不同算法在运行时间上的差异。 综上所述,数据结构程序设计项目是通过使用数据结构和算法来解决实际问题的项目,可以帮助学生深入理解数据结构和算法,并提升编程能力和解决实际问题的能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值