一、项目一问题分析
1.1 问题重述和扩展
为了实现对中国计算机设计大赛的赛事各种统计和简单分析,将参与计算机设计大赛设定为n(
)个学校,赛事m个项目,以主关键字:队伍编号/名称、项目得分、学校编号/名称、项目编号/名称、获奖情况,实现查询和排序等;以组合关键字:[学校编号/名称,得分]、[项目编号/名称,得分]、[学校编号/名称,项目编号/名称,得分],产生各种成绩单和得分报表等,比赛获奖按照每个项目的得分降序排序,取前三名。
1.2 基本需求分析
1.数据要求:每个比赛项目至少有10支参赛队;每个学校最多有6支队伍参加,项目数量在(3,10]之间,名称最大不超过20个字符;根据计算机设计大赛一般情况,考虑每个项目中,每个学校的每只队伍只参加一个项目。
2.操作要求:能够按照学校编号或名称,学校总分,各项目总分排序(两种顺序)输出;能统计各学校的总分并输出;能按照学校编号查询该学校的某个项目获奖情况或者按照项目编号查询前三名获奖的学校/队伍。
3.输入输出要求:可以输入学校的名称,赛事项目的名称,输出使用中文提示,各学校分数均为整数。输入数据中采用合法数据和非法数据测试
4.界面与文件存储要求:使用一定程度的控制台界面,功能独立,各功能模块通过输入输出数据联系;使用分隔值文件(.csv)格式存储相关赛事信息。
二、项目二问题分析
2.1 问题重述和扩展
以某校新校区的平面图为数据源,设计一个校园导游的程序,能够查询相关景点信息和任意两点之间的最短路径
2.2 基本需求分析
1.数据要求:所包含的景点不小于10个,各景点应该包含景点名称,代号,简介等相关信息;校园道路双向通行,可认为是一个无向连通图。
2.操作要求:能够为来访客人提供图中的任意景点相关信息查询;为来访客人提供图中任意两景点的最短路径查询;提供关键字查询等。
3.输入输出要求:输入景点代号/名称,关键字查询相关信息/路径;输出各景点相关信息/最短路径长度/一条最短路径(沿途经过的地方)
4.界面与文件存储要求:使用一定程度的控制台界面,功能独立,各功能模块通过输入输出数据联系;使用分隔值文件(.csv)存储相关景点信息。
三、项目三问题分析
3.1 问题重述和扩展
设计一个较简单的算术表达式计算器。
3.2 基本需求分析
1.数据要求:能够实现标准整数类型的四则运算表达式求值(包含括号,可多层嵌入),在满足此要求的基础上,又将小数部分的表达式计算实现,即兼容小数表达式的计算。
2.操作要求:为了能够提高程序的健壮度,将所提供的表达式数据用文件存储,测试时一次性读入计算,并提供各种分析报告;其次也可支持手动输入,即一次输入一条表达式(不论正确),程序可以自动判断其准确性,并给出相应反馈。
3.输入输出要求:输入算术求值表达式(文件或手动),自动输出判断的错误类型或计算相应结果。
4.界面于存储要求:使用一定程度的控制台界面,功能独立,各功能模块通过输入输出数据联系;使用分隔值文件(.csv)存储相关表达式信息。
四、主要设计思路
4.1 项目一实施细节
1.数据记录形式展示:根据所分析的要求,可以看出该赛事统计表中能唯一的标识表中的一条记录是队伍名称/编号,则选择该数据项作为主关键字作为基表,输入数据时,按以下示例输入表中每一条记录:
项目信息 | 学校信息 | 得分 | 获奖情况 |
其中队伍信息包括:名称和编号,项目信息、学校信息同样。所确定的编号一般中国计算机设计大赛官网为统一管理而确定,这里由用户输入数据提供。以下代码是具体定义:
struct School {//学校信息
int number;
string name;
};
struct Project {//项目信息
int number;
string name;
};
struct Record {//数据记录
School school;
Project project;
int scores;
int award;//获奖情况
};
struct Schoolgrades//学校成绩报表
{
string Schoolname;//存储学校名称的字符串
int Schoolnumber;
int scores;//总分
};
struct Projectgrades
{
string Projectname;
int Projectnumber;
int scores;
};
2.赛事统计表的数据结构:结合第一节的问题分析,采用逻辑相邻的链式存储结构,其优点是:插入、删除较为方便,可动态的增加数据信息(除非内存已满,否则无需考虑“上溢”),查询操作时间复杂度控制在线性量级、为了避免出现不稳定的序列,选择改进的链式选择排序,但时间复杂段较高,为立方量级。下面给出链式存储结构定义:
struct Node {
Record record;
Node* next;
};
class StatisTable
{
private:
Node* front;//
int length;//指队伍个数,能为唯一标识表中的一条记录
int ProjectNum;//项目数量
int SchoolNum;//学校数量
Schoolgrades *schgrades;
Projectgrades *progrades;
public:
StatisTable();
~StatisTable();//
Node* GetFront() { return front; }//返回头指针,用于寻找第一个节点
bool Insert(int i,Record record);//向表中第i个位置插入一条Record类型的记录,并更新文件
bool Delete(int i);//删除表中第i个位置的记录,并更新文件
bool Delete(int sign, int number);//sign表示选择学校(1)或项目(2),按指定编号删除,出错报异常或提示重新处理,并更新文件
bool Delete(int sign, string name);sign表示选择学校(1)或项目(2),按指定名称删除,出错报异常或提示重新处理,并更新文件
bool Deleterecord(int snumber, int pnumber);//删除由学校编号和项目编号确定的记录,并更新文件
int SchoolScores(int number);//根据学校编号统计总分并返回
void SchoolNumbersort(int Flag);//根据Flag值按学校编号排序,Flag-1:递增;Flag-2:递减
void Schoolnamesort(int Flag);//根据Flag值按学校名称(英文ASCII码)排序,同上
void SchoolScoresSort(int Flag);//按学校总分排序,同上
void ProjectScoresSort(int Flag);//按项目总分排序,同上
bool Search(int snumber, int pnumber);//查询由学校编号、项目编号确定的队伍的获奖情况,返回true或false
void Setinfo();//设置项目和学校有多少种类型,属于初始化操作
void Scoresort();//按照每条记录(基表)总分排序,仅用于组合关键字排序,比如先找到同项目的队伍,再使用该函数才有意义
Record* FindSchool(int number);//按项目编号查询取得前三名的学校,返回三条记录
bool ReadFile(string Filepath);//从文件中读取数据,属于初始化操作
void Update();//将内存中的数据更新至文件中,再插入,删除中含有该函数,排序可手动调用该函数更新
void print(int way);//将大部分输出结果汇总到一个输出函数,用way控制各种输出
};
3.整体的主要流程(待定):由于可能会根据程序做出进一步的测试,这里仅给出还未实现代码的思维导图(还需修正):
![](https://img-blog.csdnimg.cn/d2c209a2dbde4ddbbef91ee236fce8bb.png)
4.2 项目二实施细节
1.数据逻辑结构:该景点图为无向连通图,权值为路径长度,当任意两个景点没有邻边连接时,权值设为无穷大(用一很大的数表示即可,这里设置为10000),下图为新校区景点平面图:
![](https://img-blog.csdnimg.cn/c72eafce6cd643d3bff71c907f9bbac4.jpeg)
由此转化为下图所示的拓补图:
![]()
带权拓补图
2.数据的存储结构:采用一个一维数组vertex[i]存储景点信息,则应该开辟一个结构体数组;其次使用邻接矩阵adj[i][j]存储相应景点的权值关系:如果两景点有邻边:邻接矩阵adj[i][j]为相应权值(路径长度),反之adj[i][j]为无穷值,自身与自身的情况adj[i][i]应为0,按照上述原则即可初始化生成无向图G<V,E>。为便于动态的管理该景点图,使用文件存储相关信息,当发生变更时(比如新增加景点,新修的一条路),则可在文件中填充相关信息,避免在程序相关代码处进行更改,提高效率,同时vertex和adj应为一级指针,二级指针便于实现动态管理。如下代码所示:
struct Vertex//定义顶点结构类型,用顶点表示新校区的各景点
{
string name;//景点名称
int Code;//景点代号
string Introduction;//景点简介
};
class CampusGuide //定义校园导游类
{
private:
//该图为默认为无向联通图,即任意两个景点之间是连通的
Vertex* vertex=NULL;//用于存储图中各景点信息的数组,动态存储
int** adj=NULL;//用于存放图中边的信息,称为邻接矩阵,动态存储
int vertexnum=0, edgenum=0;//图的景点数和边数
public:
CampusGuide();//导游程序初始化,开始时向文件读取相关景点信息
~CampusGuide();//析构函数
void Setvertexnum();//设置景点个数
void Setedgenum();//设置边数
int GetVextexnum() { return vertexnum; }//返回景点个数
int GetEdgenum() { return edgenum; }//返回边数
void Searchvertex(int Code);//根据景点代号查询相关景点信息并返回
void Searchvertex(string name);//根据景点名称查询相关景点信息并返回
int LocateVex(string vertexname);//查询顶点vertexname在无向图中的位置,不在返回-1
void ShortestPath(int begincode, int endcode);//根据用户所给的两景点代号计算最小路径
void ShortestPath(string beginname, string endname);//根据用户所给的两景点名称计算最小路径
void SearchKey(string Keyname);//根据关键字求多个景点信息(若果有的话)
};
3.总体流程如下所示: 根据最后实验代码做出更加具体的修正
![](https://img-blog.csdnimg.cn/e0401909c3df4215b8143276036cc5c4.jpeg)
4.2 项目三实施细节
1.数据逻辑结构:为了便于计算,将中缀表达式转换为后缀表达式。其中需要用到两个辅助栈便于操作,第一个是操作符栈:用于将中缀表达式转换为后缀表达式所开辟的辅助栈;第二个是操作数栈:用于计算后缀表达式时所开辟的辅助栈。每次计算完毕后,将两栈置空。这里为便于整体调用,将算术求值写成类。
中缀表达式转后缀表达式:
1.从中缀表达式从左至右依次取出数据
2.如遇到操作数,直接输出到后缀的队列里。
3.如果遇到操作符(包括括号),这里再定义一个存放操作符的栈,则:
i.如果操作符是'(',入栈
ii.如果操作符是 ')' ,则把栈里的操作符依次出栈并插入到后缀序列后面,直到遇到 '('.
iii.如果操作符不是 ‘(’ 和 ‘)’ ,则:
(1). 如果操作符的优先级比top的优先级高,则入栈
(2). 如果操作符优先级等于或小于top优先级,则将top出栈并插入到后缀序列后面, pop后,再比较栈顶元素的优先级,重复iii,直到操作符优先级大于top优先级或操作符栈 为空,将此操作符入栈。
如果中序队列里的数据已经读取完毕,记录操作符的栈里,还有操作符的话,依次出栈插入到后缀序列的后面。
此时中缀就已经转换为后缀表达式,如下流程图所示:
![](https://img-blog.csdnimg.cn/2f4ef938e4e646c6b1d06d7e9cab642a.jpeg)
2.数据存储结构:使用c++自带的标准库<stack>存储上述的两个栈,另外为了对文件获得的表达式数据进行存储和后缀表达式存储,使用两个vector<string> 对象名(相当于字符串队列)进行存储,便于计算和传值,如下代码所示:
class Calculator//算术表达式求值类
{
private:
vector<string> expression;//用于接收处理之后形成的后缀表达式
vector<string> inexpression;//用于接收文件读取过来的中缀表达式
stack<string> operatorstack;//操作符栈,每次表达式求值后置为空
stack<double> operandstack;//操作数栈,每次表达式求值后置为空
public:
Calculator();//计算初始化
void ReadFile();//从文件中读取所有表达式,并存储于inexpression中
bool CheckVaild(string expression);//检查输入的表达式是否合法
void ComputeResult(double& result,string Operator);//单运算符计算
void Inordertopostorder(string inorderexp);//中缀表达式转后缀表达式并返回
void PostCompete();//后缀表达式计算
void FileDeal();//文件处理
void ManualDeal(string inputexpression);//手动处理
};
3.总体流程如下所示: 根据最后实验代码做出更加具体的修正
![](https://img-blog.csdnimg.cn/9596c47e8e964da2b17f1cce8645cfc0.jpeg)