数据结构课程设计预习报告

目录

项目一:中国计算机设计大赛赛事统计

一、问题描述

1.基本要求

2.设计要求

3.测试数据

4.实现提示

二、问题分析和任务定义

问题分析

任务定义

三、逻辑设计

1.数据类型

2.主要模块

四、物理设计

项目二:校园导游咨询

一、问题描述

1.基本要求

2.测试数据

3.实现提示

二、问题分析和任务定义

问题分析

任务定义

三、逻辑设计

1.数据类型

2.主要模块

四、物理设计

项目三:算术表达式求解

一、问题描述

1.基本要求

2.测试数据

3.实现提示

二、问题分析和任务定义

1.问题分析

2.任务定义

三、逻辑设计

1.数据类型

2.主要模块

四、物理设计


项目一:中国计算机设计大赛赛事统计

一、问题描述

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

1.基本要求

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

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

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

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

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

2.设计要求

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

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

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

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

3.测试数据

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

4.实现提示

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

二、问题分析和任务定义

问题分析

设计一个中国计算机设计大赛赛事系统,可以输入相关信息后依照用户需求进行相关的查询,还具有存储功能将录入的信息保存下来以供查询。

注意以下几点:

1.3<赛事项目数量<=10,并且每个比赛项目至少有10支参赛队;每个学校最多有6支队伍参赛,输入时需要注意;

2.学校名称长度不超过20个字符;

3.输出形式:有中文提示,各学校分数为整数;

4.每个学校每个参赛队伍只能参加一个赛事项目;

任务定义

1.成绩的录入需要我们依照设置的提示来输入相关的数据;

2.自定义一个交互式的菜单,实现以下功能:

1)统计各个学校的总分;

2)按照学校编号排序输出;

3)按照总分排序输出;

4)按照各项目总分排序输出;

5)根据学校编号查询某个项目的获奖情况。

6)根据项目编号查询取得前三名的学校

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

三、逻辑设计

1.数据类型

需要设置两个结构体,学校的结构体与比赛项目的结构体;

学校:学校id,学校名称,学校总分,学校在各项目里的总分,比赛项目数组

比赛项目:项目id,项目名称,参加该项目的队伍,分数数组,名次数组

typedef struct  
{
	int pro_id;//项目id
	char pro_name[20];//项目名称
	int pro_team;//参加该项目的队伍数量
	int score[6];//获得的分数
	int rank[6];//获得的名次
}Project;
typedef struct
{
	int sch_id;//学校id
	char sch_name[20];//学校名称
	int all_score;//学校总分
	int pro_score[pro_maxnum];//学校在各项目里的总分
	Project p[pro_maxnum];//比赛项目数组
}School;

2.主要模块

初始界面及赛事系统信息读入:初始的界面设计,读入学校数量与比赛项目数量,并进行相关初始化;

主菜单界面:根据菜单提示,选择相应的算法来完成功能的实现;

输入操作:读入相关数据,如某学校在某项目中参与了几支队伍,都取得了什么名次;

排序输出算法:分为按学校编号排序输出,按学校总分排序输出,按各项目总分排序输出;

查询算法:分为按学校编号查询,按项目编号查询;

信息存储与读入算法:保证信息可存到本地并且可以读入。

函数功能
void init()初始界面及赛事系统信息读入
void menu()主菜单
void input()输入信息
void base_input()编号与名称的读入
bool is_true()检验信息输入是否符合规定
void all_score()统计各个学校的总分
void sort_out()排序输出
void id_out()按学校编号排序
void score_out()按学校总分排序
void pro_out()按各项目总分排序
void seek()信息查询
void id_seek()按学校编号查询某个项目的获奖情况
void pro_seek()按项目编号查询取得前三名的学校
void save_tofile()数据存入文件
void read_fromfile()从文件里读取数据

四、物理设计

给出数据结构及主要函数。

结构体School:

typedef struct
{
	int sch_id;//学校id
	char sch_name[20];//学校名称
	int all_score;//学校总分
	int pro_score[pro_maxnum];//学校在各项目里的总分
	Project p[pro_maxnum];//比赛项目数组
}School;

结构体Project:

typedef struct  
{
	int pro_id;//项目id
	char pro_name[20];//项目名称
	int pro_team;//参加该项目的队伍数量
	int score[6];//获得的分数
	int rank[6];//获得的名次
}Project;

init函数:

void init()
{
	cout << "*****************************************************************************************************************" << endl;
	cout << "***                                 欢迎使用中国计算机设计大赛赛事统计系统!                                  ***" << endl;
	cout << "*****************************************************************************************************************" << endl;
	cout << "请您先输入大赛主要信息!" << endl;
	while (true)
	{
		bool flag1 = false;
		bool flag2 = false;
		cout << "学校个数:";
		cin >> sch_num;
		cout << "项目个数:";
		cin >> pro_num;
		if (sch_num >= 1 && sch_num <= 20)
			flag1 = true;
		if (pro_num > 3 && pro_num <= 10)
			flag2 = true;
		if (flag1 && flag2)
		{
			for (int i = 0; i < sch_num; i++)
			{
				s[i].all_score = 0;
				for (int j = 0; j < pro_num; j++)
				{
					s[i].pro_score[j] = 0;
				}
			}
			return;
		}
		else cout << "您输入的信息有误!请重新输入!" << endl;
	}
}

memu函数:

void menu()
{
	int ord;
	while (true)
	{
		cout << "*****************************************************************************************************************" << endl;
		cout << "***                                      您可以输入相应序号来提交请求!                                       ***" << endl;
		cout << "***                                            【1】信息录入                                                  ***" << endl;
		cout << "***                                            【2】各参赛院校总分                                            ***" << endl;
		cout << "***                                            【3】排序输出                                                  ***" << endl;
		cout << "***                                            【4】信息查询                                                  ***" << endl;
		cout << "***                                            【0】退出系统                                                  ***" << endl;
		cout << "*****************************************************************************************************************" << endl;
		cin >> ord;
		switch (ord)
		{
		case 1:
			input();
			break;
		case 2:
			all_score();
			break;
		case 3:
			sort_out();
			break;
		case 4:
			seek();
			break;
		case 0:
			cout << "感谢您的使用!" << endl;
			return;
		default: cout << "您的请求有误!请您重新输入!" << endl;
		}
	}
}

input函数:

void input()
{
	base_input();
	cout << "**************************************************" << endl;
	do
	{
		for (int i = 0; i < sch_num; i++)
		{
			for (int j = 0; j < pro_num; j++)
			{
				cout << "请输入" << s[i].sch_name << "参加" << s[i].p[j].pro_name << "的队伍个数:";
				cin >> s[i].p[j].pro_team;
				if (s[i].p[j].pro_team)
				{
					cout << "请输入各队伍的排名:";
					for (int k = 0; k < s[i].p[j].pro_team; k++)
					{
						cin >> s[i].p[j].rank[k];
						switch (s[i].p[j].rank[k])
						{
						case 0:
							s[i].p[j].score[k] = 0;
							break;
						case 1:
							s[i].p[j].score[k] = 5;
							break;
						case 2:
							s[i].p[j].score[k] = 3;
							break;
						case 3:
							s[i].p[j].score[k] = 2;
							break;
						}
						s[i].all_score += s[i].p[j].score[k];
						s[i].pro_score[j] += s[i].p[j].score[k];
					}
				}
				cout << "**************************************************" << endl;
			}
		}
	} while (!is_true());
	savetofile();
}

is_true函数:

bool is_true()
{
	bool flag = true;
	//每个学校最多有六支队伍
	for (int i = 0; i < sch_num; i++)
	{
		int cnt1 = 0;
		for (int j = 0; j < pro_num; j++)
		{
			cnt1 += s[i].p[j].pro_team;
			if (cnt1 > 6) flag = false;
		}
	}
	//每个项目至少有十个队伍参加
	for (int i = 0; i < pro_num; i++)
	{
		int cnt2 = 0;
		for (int j = 0; j < sch_num; j++)
		{
			cnt2 += s[j].p[i].pro_team;
		}
		if (cnt2 < 10) flag = false;
	}
	if (flag) return true;
	cout << "您输入的信息有误!!!" << endl;
	cout << "请注意!每个学校最多有六支队伍参赛,且每个项目至少有10支队伍参加!" << endl;
	cout << "**************************************************" << endl;
	return false;
}

all_score函数:

void all_score()
{
	cout << "id:" << '\t' << "名称:" << '\t' << "总分:" << endl;
	for (int i = 0; i < sch_num; i++)
	{
		cout << s[i].sch_id << '\t' << s[i].sch_name << '\t' << s[i].all_score << endl;
	}
}

sort_out函数:

void sort_out()
{
	int ord;
	while (true)
	{
		cout << "*****************************************************************************************************************" << endl;
		cout << "***                             您可以输入相应序号来提交请求!输入-1返回主菜单                               ***" << endl;
		cout << "***                                            【1】按学校编号输出                                           ***" << endl;
		cout << "***                                            【2】按学校总分输出                                           ***" << endl;
		cout << "***                                            【3】按各项目总分输出                                         ***" << endl;
		cout << "*****************************************************************************************************************" << endl;
		cin >> ord;
		switch (ord)
		{
		case 1:
			id_out();
			break;
		case 2:
			score_out();
			break;
		case 3:
			pro_out();
			break;
		case -1:
			return;
		default: cout << "您的请求有误!请您重新输入!" << endl;
		}
	}
}

seek函数:

void seek()
{
	int ord;
	while (true)
	{
		cout << "*****************************************************************************************************************" << endl;
		cout << "***                             您可以输入相应序号来提交请求!输入-1返回主菜单                                ***" << endl;
		cout << "***                                            【1】按学校编号查询                                            ***" << endl;
		cout << "***                                            【2】按项目编号查询                                            ***" << endl;
		cout << "*****************************************************************************************************************" << endl;
		cin >> ord;
		switch (ord)
		{
		case 1:
			id_seek();
			break;
		case 2:
			pro_seek();
			break;
		case -1:
			return;
		default: cout << "您的请求有误!请您重新输入!" << endl;
		}
	}
}

项目二:校园导游咨询

一、问题描述

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

1.基本要求

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

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

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

2.测试数据

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

3.实现提示

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

二、问题分析和任务定义

问题分析

设计一个江科大校园导游系统,可以依照用户的选择进行相关功能的实现,如查询景点信息,找到最短路径。

注意以下几点:

1.设置的时候注意景点不小于10个;

2.由于道路是双向的,因此构造无向图;

3.用Dijkstra算法解决最短路径问题。

任务定义

1.设置景点,路径相关信息,构成无向图;

2.提供校园平面图;

3.提供景点相关信息查询;

4.提供问路查询,即找到最短路径。

三、逻辑设计

1.数据类型

设置两个结构体,一个是Vertex,包括景点信息,表示点,另一个是MGraph,包括点与景点路径,表示图。

typedef struct {
	int id;//景点代号
	char name[N];//景点名称
	char syn[N];//景点简介
}Vertex;
typedef struct {
	Vertex vertex[max_vertices];//开个数组,存放景点信息
	int edges[max_vertices][max_vertices];//路径
	int vertex_num, edge_num;//图的顶点数和边数,也就是景点与路径
}Graph;

2.主要模块

  1. 初始化图上相关信息:包括景点信息,景点路径,景点个数,路径个数;

    注意!景点路径为虚拟设置,与实际路径不符!!!

  2. 主菜单:根据不同的请求调用相关函数;

  3. 查询校园平面图:把所有景点输出;

  4. 查询景点详细信息:包括代号,名字,简介;

  5. 查询最短路径;

函数功能
void init()初始化
void menu()主菜单
void plane_figure()查询校园景点平面图
void spot_info()查询景点信息
void short_path()查询最短路
void dijkstra(int sta, int fin)计算最短路径及最短路径距离

四、物理设计

关键在于最短路算法的编写

1.首先开四个数组:

int dist[max_vertices];//存储到起点的最短距离
bool st[max_vertices];//表示该点到起点的最短距离是否确定
int pre[max_vertices];//存储点的前趋点
int path[max_vertices];//存储最短路径

2.dist数组初始化为N,st数组初始化为false,pre数组各个点的前趋点初始化为自身;

3.dist[sta]为0,表示到起点自身的距离为0;

4.存在G.vertex_num个点,就迭代G.vertex_num次,每次从所有未确定最短距离的点里找到离起点最近的点,用该点来更新所有点的最短距离;

5.如果dist[fin]为N,则表示起点与终点之间没有连通的路径,若不为N,则最短路径长度为dist[fin];

6.利用一个while循环来把前趋点挨个存到path数组里,别忘了起点与终点也放进去,然后把path数组反转一下即为最短路径。

dijkstra函数:

void dijkstra(int sta, int fin)
{
	int dist[max_vertices];
	bool st[max_vertices];
	int pre[max_vertices];
	int path[max_vertices];
	
	for (int i = 0; i < G.vertex_num; i++)
	{
		dist[i] = N;
		st[i] = false;
		pre[i] = i;
	}
	dist[sta] = 0;
	
	for (int i = 0; i < G.vertex_num; i++)
	{
		int t = -1;
		for (int j = 0; j < G.vertex_num; j++)
		{
			if (!st[j] && (t == -1 || dist[j] < dist[t]))
				t = j;
		}
		st[t] = true;
		for (int j = 0; j < G.vertex_num; j++)
		{
			if (dist[t] + G.edges[t][j] < dist[j]) 
			{
				dist[j] = dist[t] + G.edges[t][j];
				pre[j] = t;
			}
		}
	}
	if (dist[fin] == N) 
	{
		cout << "两景点之间没有连通的路径!" << endl;
		return;
	}
	int total = 1, x = fin;
	path[0] = fin;
	while (pre[x] != sta)
	{
		path[total++] = pre[x];
		x = pre[x];
	}
	path[total++] = sta;

	reverse(path, path + total);

	printf("从%s到%s的最短路径为:\n", G.vertex[sta].name, G.vertex[fin].name);
	cout << G.vertex[path[0]].name;
	for (int i = 1; i < total; i++)
	{
		cout << "->" << G.vertex[path[i]].name;
	}
	cout << endl;
	printf("从%s到%s的最短路径距离为:%d\n", G.vertex[sta].name, G.vertex[fin].name, dist[fin]);
}

项目三:算术表达式求解

一、问题描述

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

1.基本要求

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

2.测试数据

(30+270)/3-123
5+(9*(62-37)+15)*6
要求自行设计非法表达式,进行程序测试,以保证程序的稳定运行。

3.实现提示

可以设计以下辅助函数:
status isNumber(char ReadInChar); //视ReadInchar 是否是数字而返回 TRUE 或 FALSE 。
int TurnToInteger(char IntChar); // 将字符’0’.’9’ 转换为整数 9。

二、问题分析和任务定义

1.问题分析

由于不同的运算符具有不同的优先级,还要考虑是否存在括号,算术表达式的求值不可能总是从左到右进行,要借助栈实现;

注意以下几点:

1.非法表达式错误形式多样,需要尽可能考虑周全;

2.题目中对于空格没有要求,因此我们设置的时候可以遇到空格跳过,也就是说空格不算非法字符,用户输入的时候可以输入空格。

2.任务定义

1.设计一个简单的算术表达式计算器,可以实现标准整数类型的四则运算表达式的求值(包含括号,可多层嵌入);

2.运算式要进行检查,若为非法则不进行计算,要求重新输入正确的运算式;

三、逻辑设计

1.数据类型

1)数据结构

设置两个栈,一个存放运算符,另一个存放操作数。

stack<double> num_stack;//用于存放操作数;
stack<char> ope_stack;//用于存放运算符;

2)基本操作

push(); //向栈顶添加元素
pop(); //从栈顶移除第一个元素
top(); //返回栈顶元素
empty(); //判断堆栈是否为空
size(); //返回栈的大小

2.主要模块

  1. 检验字符串是否合法;
  2. 检验字符是否为操作数;
  3. 进行操作数栈两个数的+,-,*,/,并把结果放到操作数栈;
  4. 从左向右扫描字符串。
函数功能
bool is_true()检验字符串是否合法
bool is_number()该字符是否为操作数
void eval()进行操作数栈两个数的+,-,*,/,并把结果放到操作数栈
double scan()从左向右扫描字符串

四、物理设计

两个核心关键点:

1.双栈,一个操作数栈,一个运算符栈;

2.运算符优先级,栈顶运算符和即将入栈的运算符的优先级比较:

(1)如果栈顶的运算符优先级低,新运算符直接入栈

(2)如果栈顶的运算符优先级高或者优先级相等,先出栈计算,新运算符再入栈

算法流程:

1.检验字符串是否合法;

2.从左到右依次扫描字符串:

1)若为操作数则放到操作数栈;

2)若为’('直接入运算符栈;

3)若为’)‘则依次出运算符栈,直到栈顶为’)‘,把’)'也出栈;

4)若为其他运算符,根据优先级进行不同的操作:若栈顶优先级大于等于即将入栈的运算符优先级,则先出栈计算,新运算符再入 栈,否则新运算符直接入栈;

3.若运算符栈里还有运算符,则依次出栈;

4.最后操作符栈顶元素即为运算结果。

evel函数:

void evel()
{
    double a = num_stack.top();//第一个操作数
    num_stack.pop();

    double b = num_stack.top();//第二个操作数
    num_stack.pop();

    char p = ope_stack.top();//运算符
    ope_stack.pop();

    double r = 0;//结果 

    //计算结果
    if (p == '+') r = b + a;
    if (p == '-') r = b - a;
    if (p == '*') r = b * a;
    if (p == '/') r = b / a;

    num_stack.push(r);//运算结果放到操作数栈
}

scan函数:

double scan(string s)
{
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == ' ') continue;
        if (is_number(s[i]))//操作数
        {
            int x = 0, j = i;//计算数字
            while (j < s.size() && is_number(s[j]))
            {
                x = x * 10 + s[j] - '0';
                j++;
            }
            num_stack.push(x);//数字入栈
            i = j - 1;//后退一位,之后会++
        }
        else if (s[i] == '(') ope_stack.push(s[i]);//遇到'('直接入栈
        else if (s[i] == ')')//遇到')'则一直弹栈
        {
            while (ope_stack.top() != '(')
                evel();
            ope_stack.pop();//把'('弹栈
        }
        else
        {
            while (ope_stack.size() && h[ope_stack.top()] >= h[s[i]])//栈顶运算符优先级大于等于新的运算符
                evel();//则不断弹栈
            ope_stack.push(s[i]);//把新的运算符放进栈里
        }
    }
    while (ope_stack.size()) evel();//如果运算符栈里还有运算符,则不断弹栈
    return num_stack.top();//栈顶操作数即为运算结果
}

is_true函数

bool is_true(string s) {
    if (!is_number(s[0]) && s[0] != '(') {
        cout << "输入错误!表达式开头必须是数字或者'('!" << endl;
        return false;
    }
    if (!is_number(s[s.size() - 1]) && s[s.size() - 1] != ')') {
        cout << "输入错误!表达式结尾必须是数字或者')'!" << endl;
        return false;
    }
    int cnt1 = 0, cnt2 = 0;
    bool flag = false;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == ' ') continue;
        if (!is_number(s[i]) && !is_ope(s[i]) && s[i] != '(' && s[i] != ')') {
            cout << "表达式错误!表达式里存在非法字符!" << endl;
            return false;
        }
        if (s[i] == ')' && !flag) {
            cout << "表达式错误!右括号出现在左括号之前!" << endl;
            return false;
        }

        if (s[i] == ')' && s[i + 1] == '(') {
            cout << "表达式错误!两个括号之间要有运算符!" << endl;
        }

        if (is_ope(s[i]) && is_ope(s[i + 1])) {
            cout << "表达式错误!运算符后面不能为运算符!" << endl;
            return false;
        }
        if (s[i] == '/' && s[i + 1] == '0') {
            cout << "表达式错误!除数不能为0!" << endl;
            return false;
        }
        if (s[i] == '(') flag = true, cnt1++;
        if (s[i] == ')') cnt2++;
    }
    if (cnt1 != cnt2)
    {
        cout << "表达式错误!左右括号不匹配!";
        cout << cnt1 << " " << cnt2 << endl;
        return false;
    }
    return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值