江苏科技大学2022数据结构实验预习报告
目录
项目1:中国计算机设计大赛赛事统计
【问题描述】
参加计算机设计大赛的n个学校编号为1~n,赛事分成m个项目,项目的编号为1~m.比赛获奖按照得分降序,取前三名,写一个统计程序产生各种成绩单和得分报表。
【基本要求】
1)每个比赛项目至少有10支参赛队;每个学校最多有6支队伍参赛;每个学校的每个参赛队伍只能参加一个赛事项目;
2)能统计各学校的总分;
3)可以按照学校编号或名称,学校的总分、各项目的总分排序输出;
4)可以按学校编号查询学校某个项目的获奖情况;可以按项目编号查询取得前三名的学校;
5)数据存入文件并能随时查询
【设计要求】
1)输入数据形式和范围:可以输入学校的名称,赛事项目的名称。
2)输出形式:有中文提示,各学校分数为整数
3)界面要求:交互设计要合理,每个功能可以设立菜单,根据提示,可以完成相关功能的要求。
4)存储结构:学生自己根据系统功能要求自己设计,但是赛事相关数据要存储在文件中。
【测试数据】
要求使用全部合法数据,整体非法数据,局部非法数据。进行程序测试,以保证程序的稳定。
【实现提示】
假设3<赛事项目数量<=10,学校名称长度不超过20个字符。每个赛事结束时,将其编号、名称输入,并依次输入参赛学校编号、学校名称和成绩。
解题思路:流程图如下
算法调用图如下:
1.为操作方便,设定一个包含所有功能选择的菜单页面;
2.考虑到所有数据都需要频繁输入输出,排列顺序,考虑使用vector容器,用sort函数辅助排序;
文档保存:
void writeToFile() {
fstream out;
out.open("data.txt", ios::out | ios::ate);
out << S << ' ' << C << ' ' << T << '\n';
for (int i = 0; i < S; i++) {
out << schools[i].getNoble();
if (first)cout << " ";
out << schools[i].getName() << "\n";
}
for (int i = 0; i < C; i++) {
out << contests[i].getNoble() << " " << (int)contests[i].isFinished();
if (first)cout << " ";
out << contests[i].getName() << "\n";
}
for (int i = 0; i < T; i++) {
out << teams[i].getNoble() << " " << teams[i].getSchool() << " " << teams[i].getContest() << " " << teams[i].getScore() << "\n";
}
out.close();
文档读取:
void readFromFile() {
fstream in;
in.open("data.txt", ios::in);
in >> S >> C >> T;
for (int i = 0; i < S; i++) {
int noble;
char s[40];
in >> noble;
in.getline(s, 40, '\n');
School x(noble, s);
insertSchool(x);
}
for (int i = 0; i < C; i++) {
int noble;
char s[40];
in >> noble;
int finished = 0;
in >> finished;
in.getline(s, 40, '\n');
Contest x(noble, s);
if (finished == 1) x.finish();
insertContest(x);
}
for (int i = 0; i < T; 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 << "读取存档成功!\n";
} //读取文档
学校信息管理:
void SchoolManage() {
char choice;
while (true) {
cout << "***********学校信息管理***********\n";
cout << "1.输出所有学校信息\n";
cout << "2.输入新的学校信息\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);
S++;
insertSchool(newAdd);
}
}
else if (choice == '0') {
writeToFile(); break;
}
}
}
比赛信息管理:
void ContestManage() {
char choice;
while (true) {
cout << "***********比赛信息编辑***********\n";
cout << "1.输入比赛结果信息\n";
cout << "2.查看比赛结果信息\n";
cout << "3.输入新的比赛信息\n";
cout << "0.返回\n";
cin >> choice;
if (choice == '1') {
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 == '2') {
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 == '3') {
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);
C++;
insertContest(newAdd);
cout << "加入成功!\n";
}
}
else if (choice == '0') { writeToFile(); break; }
}
}
队伍信息管理:
void TeamManage() {
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)];
int left = 6 - nowSchool.getNum();
cout << "要报名的队伍数(剩余容量" << left << "):";
int num;
cin >> num;
if (num > left) {
cout << "名额不足!\n";
continue;
}
else if (num < 1) {
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);
T++; 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') {
if (teams.empty())
cout << "当前队伍为空\n";
else printTeamList();
}
else if (choice == '0') {
writeToFile();
return;
}
}
}
学校获奖信息查询:
void AwardQuery() {
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())];
if (nowContest.isFinished()) { //查找前三中是否有该队伍
for (int i = 0; i < 3; i++) {
if (nowContest.getNum(i) == nowTeam.getNoble()) {
cout << nowSchool.getName() << "的队伍在编号为" << nowContest.getNoble() << "的" << nowContest.getName() << "比赛中,获得了" << i + 1 << "等奖\n";
isFind = true;
}
}
}
}
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 {
for (int i = 0; i < 3; i++) {
Team& nowTeam = teams[findTeam(now.getNum(i))];
cout << i + 1 << "等奖:" << schools[findSchool(nowTeam.getSchool())].getName() << "的队伍(编号" << nowTeam.getNoble() << ") 分数为:" << nowTeam.getScore() << endl;
}
}
}
}
else if (choice == '0') {
writeToFile();
return;
}
}
}
总分查询:
void ScoreRank() {
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);
for (int i = 0; i < m; i++) {
cout << "No." << i + 1 << "\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 MedalRank() {
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 < C; i++) {
contests[i].rank();
}
for (int i = 0; i < S; 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;
}
项目2:校园导游咨询
【问题描述】
设计一个校园导游程序,为来访的客人提供各种信息查询服务。
【基本要求】
(1) 设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息。
(2) 为来访客人提供图中任意景点相关信息的查询。
(3) 为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径。
【测试数据】
以江苏科技大学长山校区为例。
【实现提示】
一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向网.顶点和边均含有相关信息.
解题思路:
本校高清地图及主要景点路径构成的拓扑图如下:
(实验数据与实际生活无必然联系)
程序流程图如下:
算法基本函数调用图:
该校园导航系统是基于图的相关知识来设计的系统。将校园各个景点作为图的节点,各个顶点之间的路径作为图的边,边之间的距离作为节点间的权值,抽象成一个加权无向图,并将其转化为邻接矩阵,设计出能快速找到一个景点到另一个景点的最短路径及最短距离的简单程序
核心算法
1.Dijkstra算法
}
for (i = 1; i <= m.vetnum; i++)//数组初始化
{
final[i] = 0;//全部顶点初始化为未找到路径
ShortPathwet[i] = m.mat[v0][i].weight;//将与v0有连线的路径加上权值
Pathside[i] = 0;//初始化路径数组为0
}
ShortPathwet[v0] = 0;
final[v0] = 1;
for (i = 1; i <= m.vetnum; i++)
{
min = Infinity;
for (j = 1; j <= m.vetnum; j++)//找出离当前指向顶点最近的点
{
if (!final[j] && ShortPathwet[j] < min)//未被访问且存在边
{
k = j;
min = ShortPathwet[j];
}
}
final[k] = 1;//将找到的离当前顶点最近的置1
for (j = 1; j <= m.vetnum; j++)
{
if (!final[j] && (min + m.mat[k][j].weight < ShortPathwet[j]))
{
ShortPathwet[j] = min + m.mat[k][j].weight;//修改当前最优路径长度
Pathside[j] = k;//存放前驱结点
}
}
}//Dijkstr算法主体
2.floyd算法
void floyd(mapstr m)
{
int i, j, k;
for (i = 1; i <= vertex; i++)//将图的邻接矩阵赋值给 shortest二维数组,将矩阵pathh全部初始化为-1
{
for (j = 1; j <= vertex; j++)
{
shortest[i][j] = m.mat[i][j].weight;
pathh[i][j] = j;
}
}
printf("\n");
for (k = 1; k <= vertex; k++)//核心操作,完成了以k为中间点对所有的顶点对(i,j)进行检测和修改
{
for (i = 1; i <= vertex; i++)
{
for (j = 1; j <= vertex; j++)
{
if (shortest[i][j] > shortest[i][k] + shortest[k][j])
{
shortest[i][j] = shortest[i][k] + shortest[k][j];
pathh[i][j] = pathh[i][k];//记录一下所走的路 //P数组用来存放前驱顶点
}
}
}
}
}//floyd算法
项目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.使用栈来解决该问题;
2.将中缀表达式写成后缀表达式;
①从中缀表达式中从左往右依次取出数据
②如遇到操作数,直接输出到后缀的队列里。
③如果遇到操作符(包括括号),再定义一个存放操作符的栈,则:
Ⅰ.如果是操作符‘#’,改变运算状态;
Ⅱ.如果操作符是'(',入栈;
Ⅲ.如果操作符是')',则把栈里的操作符依次出栈并插入到后缀序列后面,直到遇到'('.
Ⅳ.如果操作符不是‘(’和‘)’,则:
(1). 如果操作符的优先级比top的优先级高,则入栈
(2).如果操作符优先级等于或小于top优先级,则将top出栈并插入到后缀序列后面,pop后,再比较栈顶元素的优先级,重复iii,直到把此操作符插入,将此操作符入栈。
3.后缀表达式求值
①.从左至右扫描表达式,遇到数字时,将数字压入栈中,遇到运算符时,弹出栈顶的两个数,其中先出栈的是右操作数,后出栈的是左操作数。
②.用运算符对它们做相应的计算,将结果重新入栈;
③.重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
算法流程图
核心代码
while (Goon != 0)
{
do {
c = getOperand(OPND, c);
if (c == '#')
flag = Judge(flag);//通过首符号是否为#来判定程序是否运行
switch (c)
{
case '#'://若为开始或结束运算符
if (flag == 0) //当前运行状态为结束,则得出表达式结果
{
double result;//表达式结果
while (StackEmpty(OPTR) != 1) //若运算符栈内还有运算符
Operation(OPTR, OPND);//循环运算,消去所有运算符,得到结果压入操作数栈
Pop(&OPND, &result);//此时操作数栈内的数即结果,取出结果并输出
Goon = 0;
cout << "运算结果为:" << result << endl;
}
break;
case ')'://若输入为右括号,不入栈
while (GetTop<SqStack<char>, char>(OPTR) != '(')//匹配运算符栈内的左括号
Operation(OPTR, OPND);//将左括号内的所有运算得到结果,并压入操作数栈
Pop(&OPTR, &t);//弹出左括号
break;
case '*':
Push(&OPTR, c);//"*"直接入栈
break;
case '/':
Push(&OPTR, c);//"/"直接入栈即可
break;
case '('://若输入为左括号,在已入栈运算符中优先级最高,在未入栈运算符中最低,相当于新的栈底
Push(&OPTR, c);//"("直接入栈即可
break;
case '+'://若输入加号,在已入栈运算符中仅高于左括号
t = GetTop<SqStack<char>, char>(OPTR);//判断栈顶优先级是否更高
if (t == '*' || t == '/')
while (t != 0 && t != '(') //若有优先级更高的运算符将栈底或左括号前的全部运算符计算出结果
{
Operation(OPTR, OPND);
t = GetTop<SqStack<char>, char>(OPTR);//判断是否到达栈底
}
Push(&OPTR, c);//此时已无优先级更高的运算符,将加号入栈
break;
case '-'://若输入减号,在已入栈运算符中仅高于左括号
t = GetTop<SqStack<char>, char>(OPTR);//判断栈顶优先级是否更高
if (t == '*' || t == '/')//若有优先级更高的运算符
while (t != 0 && t != '(')//将栈底或左括号前的全部运算符计算出结果
{
Operation(OPTR, OPND);
t = GetTop<SqStack<char>, char>(OPTR);//判断是否到达栈底
}
Push(&OPTR, c);//此时已无优先级更高的运算符,将减号入栈