Merge branch '杨腾泽'

master
yangtengze 1 year ago
commit 81db3eecb7

@ -2,9 +2,27 @@
# 项目名称 城市公路导航系统 # 项目名称 城市公路导航系统
### 成员
杨腾泽,刘鑫成,李培毅,孙英皓 杨腾泽,刘鑫成,李培毅,孙英皓
**摘要** **摘要**:本项目针对什么问题,实现了哪些功能。为了有效地存储和处理何种数据,采用了何种数据结构。为了解决什么问题,采用了什么算法,算法效率如何。针对其他特定需求做了哪些工作。项目的整体效果如何,有何亮点和创新。
任务分工及完成情况。
| 任务 | 设计 | 测试 |
| ---- | ---- | ---- |
| 1. 系统分析 | 李培毅 | 刘鑫成 |
| 2. 系统设计 | 杨腾泽 | 孙英皓 |
| 3. 系统实现 | 刘鑫成 | 杨腾泽 |
| 4. 系统测试 | 孙英皓 | 李培毅 |
工作量占比。
| 杨腾泽 | 孙英皓 | 李培毅 | 刘鑫成 |
|--------|-------|---------|-------|
| 25 | 25 | 25 | 25 |
(1) 基于真实的公路数据建立导航地图模型,编制成格式简单的数据文件包括城市线路名称、站点名称。 (1) 基于真实的公路数据建立导航地图模型,编制成格式简单的数据文件包括城市线路名称、站点名称。
(2)系统能够读取公路导航地图数据文件,建立公路模型,也能够将模型输出成数据文件,以便验证模型的正确性。 (2)系统能够读取公路导航地图数据文件,建立公路模型,也能够将模型输出成数据文件,以便验证模型的正确性。
@ -19,11 +37,24 @@
交通网络中常常提出这样的问题:从甲地到乙地之间是否有公路连通?在有多条通路的情况下,哪一条路最短?导航系统便可以解决这样的问题。与此同时,城市的扩建,新地点的添加,新道路的修建,需要导航系统具备添加新地点,添加新路线的功能。而受一些生态工程的实施,例如退耕还林还草,和自然条件的影响,本来存在的一些地点或道路需要删除或更改,此时导航图还应该及时的更新,以适应新的查找两点间最短路径的需要。 交通网络中常常提出这样的问题:从甲地到乙地之间是否有公路连通?在有多条通路的情况下,哪一条路最短?导航系统便可以解决这样的问题。与此同时,城市的扩建,新地点的添加,新道路的修建,需要导航系统具备添加新地点,添加新路线的功能。而受一些生态工程的实施,例如退耕还林还草,和自然条件的影响,本来存在的一些地点或道路需要删除或更改,此时导航图还应该及时的更新,以适应新的查找两点间最短路径的需要。
除此之外,用户的查找应是极为方便的,对于最短路线, 新添加的地点和路径以及删除的地点和路径的感知应是直观的,这样才能真正的给使用导航系统的人们提供方便。 除此之外,用户的查找应是极为方便的,对于最短路线, 新添加的地点和路径以及删除的地点和路径的感知应是直观的,这样才能真正的给使用导航系统的人们提供方便。
1基于真实的公路地图数据建立导航地图模型编制成格式简单的数据文件包括城市名称以及邻近城市之间的公路里程数。
2系统能够读取导航地图数据文件建立地图模型也能够将模型输出成地图数据文件以便验证模型的正确性。
3通过人机交互的方式输入起点和终点城市名称系统给出最短路径和导航路径上途径的城市名称。
4能够读取不同的导航地图进行功能测试。
要求系统运行正常、功能完整;数据结构使用得当,算法有较高的效率;代码规范、可读性高,结构清晰;具备一定的健壮性、可靠性和可维护性。
## 1.2 可行性分析 ## 1.2 可行性分析
明确解决问题的关键:最关路径算法。 地图可以用图结构建立模型,每个城市作为图中的一个顶点,城市之间的公路对应图中的边。给定起点和终点的条件下,可以利用最短路径算法求得导航路径。
核心数据结构:图。
核心算法:Dijkstra 真实的公路地图数据需要经过预先处理,编辑并保存成便于程序读取和处理的格式。在数据量比较大的情况下,要根据数据的特点采用合适的数据结构。
除了基于真实数据的测试,还可以采用小规模的模拟数据进行测试,以便验证算法的正确性。
明确解决问题的关键,核心数据结构,核心算法等。
确定解决问题的总体思路和方案:使用dijkxtra最短路径进行计算。 确定解决问题的总体思路和方案:使用dijkxtra最短路径进行计算。
@ -93,6 +124,14 @@ short.h
# 2. 系统设计 # 2. 系统设计
## 2.1 概要设计 ## 2.1 概要设计
@ -107,6 +146,63 @@ short.h
首先,分析对比几种可选的数据结构设计方案。如图可以采用邻接矩阵,也可以采用邻接表,表示集合可以用普通的查找表,还可以用不相交集。给出每一种设计方案的特点(优势、不足等)。然后,综合考虑各种因素(空间、时间、乃至团队成员的水平等),给出你的选择。 首先,分析对比几种可选的数据结构设计方案。如图可以采用邻接矩阵,也可以采用邻接表,表示集合可以用普通的查找表,还可以用不相交集。给出每一种设计方案的特点(优势、不足等)。然后,综合考虑各种因素(空间、时间、乃至团队成员的水平等),给出你的选择。
### 1xxx结构
给出核心数据结构的设计,包括文字描述和示意图。讲清楚数据是如何组织的。多个数据结构,逐一列出。
### 2xxx结构
给出核心数据结构的设计,包括文字描述和示意图。讲清楚数据是如何组织的。
###
## 2.3 算法设计
首先,分析对比几种可选的算法设计方案。如是否排序,广度优先或深度优先搜索等。给出每一种设计方案的特点(优势、不足)。然后,综合考虑各种因素(空间、时间、乃至团队成员的水平等),给出你的选择。
### 1Dijkstra算法
求最短路径Dijkstra算法的实现
设置Visited[]保存是否被标记Dis[]保存用户起点到下标号的节点路径的长度Father[]保存最短路径上的前一个节点。其他类似于Prim算法。
算法主体有三步:
1.更新:找到这样的两个顶点 即 i位置已经被访问 且j位置未被访问 且ij有连接把(0,i)+ij和(0,j)中的较小者赋给j并且Father[j] = i即i作为j的前驱节点。
2.访问每轮在更新Dis后 判断最小未被标记的顶点 对其访问vis = 1;
3.重复1、2 步骤直到Visited[]的值全为1为止。
然后是输出语句:
输出用户输入位置到其他各个顶点的最短路径长度:
直接一个循环输出Dis数组的前n位即可
输出用户输入位置到其他各个顶点的最短路径对应的路线:
首先设置i从0到n的循环每次都将i赋值给VVV作为终点v是用户输入的起点位置。
```
while (Father[vvv] != -1 && Father[vvv] != v)
{
cout << Father[vvv] << "<--";
vvv = Father[vvv];
}
```
根据Father数组内存的节点的前驱关系输出路线。
以上是迪杰斯特拉算法的基础部分,
在本程序中由于多次调用了此算法为了减少重复的代码提高代码的复用性于是在此算法中增加了一个接口即一个switch case开关语句调用迪杰斯特拉时需要在参数列表中给出需要进入的部分以实现不同的功能。
给出核心算法的设计,包括伪代码或流程图。多个核心算法,逐一列出。只列举解决问题的核心算法,重点讲清楚是如何解决问题的。
### 2XXX算法
给出核心算法的设计,包括伪代码或流程图。
# 3. 系统实现 # 3. 系统实现
@ -115,28 +211,33 @@ short.h
本程序首先是用户编辑界面用户根据自己的需求编写地图从而加入顶点的数组之中创建的地图用邻接矩阵存储在从主函数之中进行调用实现对两个算法的调用。用户在输入顶点以及边的信息都会存储在存储成功之后会提示用户存储成功之后进入到菜单界面菜单界面提供两种选择口合分别可以调运Dijkstra和Floyd算法调用之后输入相应的口令以及要查询的城市编号 算法会根据邻接矩阵存储的地图进行计算求出最短路径。在以后使用完系统后可输入口合 0系统会结束一切运算退出程序。 本程序首先是用户编辑界面用户根据自己的需求编写地图从而加入顶点的数组之中创建的地图用邻接矩阵存储在从主函数之中进行调用实现对两个算法的调用。用户在输入顶点以及边的信息都会存储在存储成功之后会提示用户存储成功之后进入到菜单界面菜单界面提供两种选择口合分别可以调运Dijkstra和Floyd算法调用之后输入相应的口令以及要查询的城市编号 算法会根据邻接矩阵存储的地图进行计算求出最短路径。在以后使用完系统后可输入口合 0系统会结束一切运算退出程序。
## 3.1 核心数据结构的实现 ## 3.1 核心数据结构的实现
核心算法Dijkstra ```cpp
算法floyd struct ArcCell
项目文件结构可以设计为: {
int length;//边的长度,既两个地点之的长
-CityRoadNav/ int money;
- CityRoadNav.vcxproj // Visual Studio项目文件 }; //定义边的类型
- CityRoadNav.vcxproj.filters
- CityRoadNav.slnSource Files/ // 源代码目录 struct VertexType
- CityNetwork.cpp // 城市网络类,存储城市数据及邻接矩阵 { int no; //顶点的编号
- CityNetwork.h char sight[10]; //地点
- Dijkstra.cpp // Dijkstra算法类,实现最短路径搜索 char introduction[100]; //地点的介绍
- Dijkstra.h }; //定义顶点的类型
- DynamicProgramming.cpp // 动态规划算法类,实现最优路径搜索
- DynamicProgramming.h struct MatGrath
- main.cpp // 主程序 {
- ...Header Files/ // 头文件目录 int vexnum; //顶点数
- ...Resources/ // 资源文件目录 int arcnum; //边数
- CityInfo.txt // 城市信息及邻接矩阵 VertexType vexs[NO]; //在图结构体中调用点的结构体
ArcCell arc[NO][NO]; //在图结构体中调用边的结构体
如以下代码,采用迪杰斯特拉算法实现求取路径最短值 };
``` ```
int Ppath2(MatGrath &G,int path[],int i,int v) //前向递归查找路径上的顶点 int Ppath2(MatGrath &G,int path[],int i,int v) //前向递归查找路径上的顶点
{ {
@ -210,6 +311,13 @@ int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找
## 3.2 核心算法的实现 ## 3.2 核心算法的实现
主函数可以分为以下几个模块: 主函数可以分为以下几个模块:
1. 数据读取模块:读取CityInfo.txt文件,构建城市网络,存储在邻接矩阵中。 1. 数据读取模块:读取CityInfo.txt文件,构建城市网络,存储在邻接矩阵中。
@ -218,10 +326,66 @@ int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找
4. 路径查询模块:选择Dijkstra算法或动态规划算法计算路径,并返回路径信息。 4. 路径查询模块:选择Dijkstra算法或动态规划算法计算路径,并返回路径信息。
5. 路径显示模块:将计算得到的路径用可视化方式显示给用户。 5. 路径显示模块:将计算得到的路径用可视化方式显示给用户。
核心算法Dijkstra 在验证到其他城市中间不超过 2 个城市时新建一个二维数组将原二维数组中的权值全部改为1这样用dijkstra算法得到的权值最小的路径就经过节点最少的路径。
算法floyd
```cpp
//Dijkstra算法
void Ppath(MatGrath &G,int path[],int w,int v) //前向递归查找路径上的顶点
{
int k;
k=path[w];
if (k==v) return; //找到了起点则返回
Ppath(G,path,k,v); //找顶点k的前一个顶点
printf("%s->",G.vexs[k].sight); //输出顶点k
}
int ShortestPath(MatGrath &G,int v,int w)//求两点之间的最短路径
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u;
for (i=0; i<G.vexnum; i++)
{
dist[i]=G.arc[v][i].length; //距离初始化
s[i]=0; //s[]置空
if (G.arc[v][i].length<INF) //
path[i]=v; //v到i有边
else
path[i]=-1; //v到i没有边置顶点i的前一个顶点为-1
}
s[v]=1;
path[v]=0; //源点编号v放入s中
for (i=0; i<G.vexnum; i++) //
{
mindis=INF; //mindis置最小长度初值
for (j=0; j<G.vexnum; j++) //su
if (s[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1; //顶点u加入s中
for (j=0; j<G.vexnum; j++) //s
if (s[j]==0)
if (G.arc[u][j].length<INF && dist[u]+G.arc[u][j].length<dist[j])
{
dist[j]=dist[u]+G.arc[u][j].length;
path[j]=u;
}
}
如以下代码,采用迪杰斯特拉算法实现求取路径最短值 if (s[w]==1)
{
printf(" 从%s到%s的最短路径长度为:%d米\t路径为:",G.vexs[v].sight,G.vexs[w].sight,dist[w]);
printf("%s->",G.vexs[v].sight); //输出路径上的起点
Ppath(G,path,w,v); //输出路径上的中间点
printf("%s\n",G.vexs[w].sight); //输出路径上的终点
}
if(s[w]==0)
printf("从%d到%d不存在路径\n",v,w);
}
``` ```
int Ppath2(MatGrath &G,int path[],int i,int v) //前向递归查找路径上的顶点 int Ppath2(MatGrath &G,int path[],int i,int v) //前向递归查找路径上的顶点
{ {
@ -294,6 +458,14 @@ int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找
``` ```
# 4. 系统测试 # 4. 系统测试
描述测试的思路和方法。比如,先用小数据量进行测试,再用真实数据进行测试。 描述测试的思路和方法。比如,先用小数据量进行测试,再用真实数据进行测试。
@ -318,6 +490,15 @@ int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找
# 5. 总结 # 5. 总结
概况项目和完成情况。 概况项目和完成情况。
@ -326,7 +507,8 @@ int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找
个人小结: 个人小结:
杨腾泽: 杨腾泽:通过这次数据结构课程设计,我对《数据结构》这门课程有了更深一步的了解,使我对《数据结构》这门课程掌握以及运用更加灵活·同时也让我发现了自已在这门课上的不足与缺陷,同时也明确了自己在以后的类似课程中的具体学习方法。
这次在应用中我发现了自己的很多不足在编写城市公路导航系统的过程中自己C语言方面的只是掌握太少很多功能需求只能退而求其次一次又一 次的更改,一次又一次的失败,也终于是在最后也完成了自己的要求,同时我也 知道了平时用功学习的重要性。尤其是在日常学习之中,对于单一的只是点也许 掌握的还不错,但是自己动手太少,实践经验严重不足,且面临课程设计之时,要求多方面的只是结和编码,对于我而言还是有很大的难度的。 如此次对于邻接 矩阵的存储于读取,以及最短路算法的实现,两个及其重要的算法,狄克斯特算法和佛洛依德算法,在具体的应用上还是有很多不足
刘鑫成:本次的系统研发研活动,让我体验到了程序开发的复杂性与程序开发成功的自豪感,一个项目的完成离不开一个团队的团结协作,在进行项目时,需要对其进行反复的纠错和改进,在更改和发现中不断地改进和提升自,从而丰富自己。这次团队体验,让我能够初步地体会到一个团队间的分工协作的重要性,成员分工以及项目领导者的重要性,让我受益匪浅 刘鑫成:本次的系统研发研活动,让我体验到了程序开发的复杂性与程序开发成功的自豪感,一个项目的完成离不开一个团队的团结协作,在进行项目时,需要对其进行反复的纠错和改进,在更改和发现中不断地改进和提升自,从而丰富自己。这次团队体验,让我能够初步地体会到一个团队间的分工协作的重要性,成员分工以及项目领导者的重要性,让我受益匪浅
@ -339,7 +521,5 @@ int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找
# 参考文献 # 参考文献
列出参考的文献资料,根据情况自行添加。
[1] 严蔚敏, 吴伟民. 数据结构C语言版. 北京: 清华大学出版社, 2007. [1] 严蔚敏, 吴伟民. 数据结构C语言版. 北京: 清华大学出版社, 2007.
[山东省国道里程表](http://www.onegreen.net/maps/HTML/50213.html)

@ -0,0 +1,141 @@
#include"type.h"
#include <string.h>
/***********************
***********************/
int CreatGrath(MatGrath &G)//进行图的创建
{
int i,j;
G.vexnum=10; //说明图的顶点的数目
G.arcnum=14; //说明图的边的数目
for(i=1;i<=G.vexnum;i++)
{
G.vexs[i].bianhao=i;
}
strcpy(G.vexs[1].sight,"济南市");
strcpy(G.vexs[2].sight,"德州市");
strcpy(G.vexs[3].sight,"淄博市");
strcpy(G.vexs[4].sight,"潍坊市");
strcpy(G.vexs[5].sight,"烟台市");
strcpy(G.vexs[6].sight,"威海市");
strcpy(G.vexs[7].sight,"青岛市");
strcpy(G.vexs[8].sight,"日照市");
strcpy(G.vexs[9].sight,"临沂市");
strcpy(G.vexs[10].sight,"济宁市");
strcpy(G.vexs[11].sight,"泰安市");
strcpy(G.vexs[12].sight,"滨州市");
strcpy(G.vexs[13].sight,"菏泽市");
strcpy(G.vexs[14].sight,"即墨市");
strcpy(G.vexs[15].sight,"胶州市");
strcpy(G.vexs[16].sight,"胶南市");
strcpy(G.vexs[17].sight,"诸城市");
strcpy(G.vexs[18].sight,"高密市");
strcpy(G.vexs[19].sight,"安丘市");
strcpy(G.vexs[20].sight,"莒县");
strcpy(G.vexs[21].sight,"平度市");
strcpy(G.vexs[22].sight,"莱西市");
strcpy(G.vexs[23].sight,"莱阳市");
strcpy(G.vexs[24].sight,"海阳市");
strcpy(G.vexs[25].sight,"乳山市");
strcpy(G.vexs[26].sight,"文登市");
strcpy(G.vexs[27].sight,"荣成市");
strcpy(G.vexs[28].sight,"牟平区");
strcpy(G.vexs[29].sight,"蓬莱市");
strcpy(G.vexs[30].sight,"栖霞市");
strcpy(G.vexs[31].sight,"莱州市");
strcpy(G.vexs[32].sight,"招远市");
strcpy(G.vexs[33].sight,"龙口市");
strcpy(G.vexs[34].sight,"昌邑市");
strcpy(G.vexs[35].sight,"昌乐");
strcpy(G.vexs[36].sight,"孝光市");
strcpy(G.vexs[37].sight,"青州市");
strcpy(G.vexs[38].sight,"临朐");
strcpy(G.vexs[39].sight,"沂水");
strcpy(G.vexs[40].sight,"广饶");
strcpy(G.vexs[41].sight,"东营市");
strcpy(G.vexs[42].sight,"沂源");
strcpy(G.vexs[43].sight,"恒台");
strcpy(G.vexs[44].sight,"博兴");
strcpy(G.vexs[45].sight,"博山");
strcpy(G.vexs[46].sight,"沂南");
strcpy(G.vexs[47].sight,"蒙阴");
strcpy(G.vexs[48].sight,"莱芜市");
for(i=0;i<G.vexnum;i++)
{
for(j=0;j<G.vexnum;j++)
{
G.arc[i][j].length=INF;
}
}
G.arc[7][14].length=G.arc[14][7].length=51;
G.arc[7][15].length=G.arc[15][7].length=41;
G.arc[15][16].length=G.arc[16][15].length=47;
G.arc[15][17].length=G.arc[17][15].length=65;
G.arc[16][17].length=G.arc[17][16].length=70;
G.arc[17][18].length=G.arc[18][17].length=56;
G.arc[17][19].length=G.arc[19][17].length=139;
G.arc[17][20].length=G.arc[20][7].length=200;
G.arc[15][21].length=G.arc[21][15].length=52;
G.arc[18][21].length=G.arc[21][18].length=54;
G.arc[14][22].length=G.arc[22][14].length=83;
G.arc[21][22].length=G.arc[22][21].length=48;
G.arc[22][23].length=G.arc[23][22].length=19;
G.arc[23][25].length=G.arc[25][23].length=104;
G.arc[24][25].length=G.arc[25][24].length=39;
G.arc[14][24].length=G.arc[24][14].length=96;
G.arc[25][26].length=G.arc[26][25].length=59;
G.arc[26][27].length=G.arc[27][26].length=35;
G.arc[25][28].length=G.arc[28][25].length=71;
G.arc[6][28].length=G.arc[28][6].length=52;
G.arc[5][28].length=G.arc[28][5].length=30;
G.arc[6][26].length=G.arc[26][6].length=45;
G.arc[5][23].length=G.arc[23][5].length=115;
G.arc[23][30].length=G.arc[30][23].length=43;
G.arc[23][31].length=G.arc[31][23].length=35;
G.arc[29][30].length=G.arc[30][29].length=64;
G.arc[5][29].length=G.arc[29][5].length=78;
G.arc[29][33].length=G.arc[33][29].length=61;
G.arc[29][32].length=G.arc[32][29].length=67;
G.arc[30][32].length=G.arc[32][30].length=42;
G.arc[22][32].length=G.arc[32][22].length=41;
G.arc[31][33].length=G.arc[33][31].length=68;
G.arc[31][34].length=G.arc[34][31].length=70;
G.arc[19][34].length=G.arc[34][19].length=79;
G.arc[4][34].length=G.arc[34][4].length=33;
G.arc[4][19].length=G.arc[19][4].length=27;
G.arc[8][17].length=G.arc[17][8].length=70;
G.arc[8][16].length=G.arc[16][8].length=94;
G.arc[8][20].length=G.arc[20][8].length=50;
G.arc[4][35].length=G.arc[35][4].length=40;
G.arc[4][36].length=G.arc[36][4].length=40;
G.arc[36][37].length=G.arc[37][36].length=28;
G.arc[36][41].length=G.arc[41][36].length=47;
G.arc[36][40].length=G.arc[40][36].length=36;
G.arc[40][44].length=G.arc[44][40].length=28;
G.arc[43][44].length=G.arc[44][43].length=33;
G.arc[44][12].length=G.arc[12][44].length=34;
G.arc[3][43].length=G.arc[43][3].length=43;
G.arc[12][44].length=G.arc[44][12].length=34;
G.arc[12][41].length=G.arc[41][12].length=66;
G.arc[3][37].length=G.arc[37][3].length=50;
G.arc[35][37].length=G.arc[37][35].length=49;
G.arc[38][37].length=G.arc[37][38].length=23;
G.arc[4][39].length=G.arc[39][4].length=89;
G.arc[39][46].length=G.arc[46][39].length=25;
G.arc[39][42].length=G.arc[42][39].length=86;
G.arc[42][45].length=G.arc[45][42].length=53;
G.arc[42][48].length=G.arc[48][42].length=43;
G.arc[3][45].length=G.arc[45][3].length=84;
return 1;
}

@ -7,7 +7,7 @@
***********************/ ***********************/
int search(MatGrath &G) int Search(MatGrath &G)
{ int a; { int a;
int flag=1; int flag=1;
printf("请输入您要查询的城市编号\n"); printf("请输入您要查询的城市编号\n");
@ -22,8 +22,8 @@
else else
{ flag=0; { flag=0;
printf("编号 景点名称 简介 \n"); printf("编号 景点名称 \n");
printf(" %-4d %-16s%-58s\n",G.vexs[a].no,G.vexs[a].sight,G.vexs[a].introduction); printf(" %-4d %-16s\n",G.vexs[a].bianhao,G.vexs[a].sight);
; ;
} }
} }
@ -36,12 +36,12 @@
***********************/ ***********************/
int addbian(MatGrath &G) void AddEdge(MatGrath &G)
{ int b,c,d; { int b,c,d;
int i,j; int i,j;
printf("请输入你要增加的边的两个点\n"); printf("请输入你要增加的路径的两个城市\n");
scanf("%d %d",&b,&c); scanf("%d %d",&b,&c);
printf("请输入你要增加的边的权值\n"); printf("请输入你要增加的路径的距离\n");
scanf("%d",&d); scanf("%d",&d);
for (i=1; i<=G.vexnum;i++) for (i=1; i<=G.vexnum;i++)
for (j=1;j<=G.vexnum;j++) for (j=1;j<=G.vexnum;j++)
@ -58,7 +58,7 @@
***********************/ ***********************/
int adddian(MatGrath &G) void AddVertices(MatGrath &G)
{ {
int a; int a;
int b; int b;
@ -69,27 +69,23 @@
int flag; int flag;
printf("请输入该城市的编号\n"); printf("请输入该城市的编号\n");
scanf("%d",&a); scanf("%d",&a);
G.vexs[a].no=a; G.vexs[a].bianhao = a;
while(flag) while(flag)
{ {
if(a>=0&&a<=G.vexnum) if(a>=0&&a<=G.vexnum)
{ {
printf("编号已经存在,请重新输入\n"); printf("编号已经存在,请重新输入\n");
scanf("%d",&a); scanf("%d",&a);
G.vexs[a].no=a; G.vexs[a].bianhao = a;
} }
else else
flag=0; flag=0;
} }
printf("请输入你要连接的点权值和所需费用\n"); printf("请输入你要连接的点权值\n");
scanf("%d",&b);
scanf("%d",&c);
scanf("%d",&d); scanf("%d",&d);
G.arc[a][b].money=G.arc[a][b].money=c;
G.arc[a][b].length=G.arc[b][a].length=d; G.arc[a][b].length=G.arc[b][a].length=d;
scanf("%s",G.vexs[a].sight); scanf("%s",G.vexs[a].sight);
scanf("%s",G.vexs[a].introduction);
G.vexnum++; G.vexnum++;
} }
@ -100,7 +96,7 @@
***********************/ ***********************/
int modify(MatGrath &G) void modify(MatGrath &G)
{ int a; { int a;
int flag=1; int flag=1;
@ -120,8 +116,6 @@
printf("请输入你要修改的信息\n"); printf("请输入你要修改的信息\n");
scanf("%s",G.vexs[a].sight); scanf("%s",G.vexs[a].sight);
scanf("%s",G.vexs[a].introduction);
} }
/*********************** /***********************
@ -135,7 +129,7 @@
printf("城市编号 城市名称 城市介绍\n"); printf("城市编号 城市名称 城市介绍\n");
for (i=1; i<=G.vexnum;i++) for (i=1; i<=G.vexnum;i++)
{ {
printf("% -9d % -10s %-15s\n",G.vexs[i].no,G.vexs[i].sight,G.vexs[i].introduction); printf("% -9d % -10s\n",G.vexs[i].bianhao,G.vexs[i].sight);
} }
return 0; return 0;
} }
@ -149,7 +143,7 @@
int DFS(MatGrath &G,int m)//深度优先搜索 int DFS(MatGrath &G,int m)//深度优先搜索
{ {
int i; int i;
printf("%d %s %s\n",G.vexs[m].no,G.vexs[m].sight,G.vexs[m].introduction); printf("%d %s\n",G.vexs[m].bianhao,G.vexs[m].sight);
visited[m]=true; visited[m]=true;
for(i=1;i<=G.vexnum;i++) for(i=1;i<=G.vexnum;i++)
{ {
@ -169,10 +163,6 @@
***********************/ ***********************/
int delet(MatGrath &G,int y,int x) int delet(MatGrath &G,int y,int x)
{ {
G.arc[x][y].length=G.arc[y][x].length=INF; G.arc[x][y].length=G.arc[y][x].length=INF;
return 0; return 0;
} }

@ -2,8 +2,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "type.h"
#include <malloc.h> #include <malloc.h>
#include "type.h"
#include "menu.h"
#include "function.h"
#include "creat.h"
#include "short.h"
int CreatGrath(MatGrath &G); //创造图 int CreatGrath(MatGrath &G); //创造图
int DFS(MatGrath &G,int m); int DFS(MatGrath &G,int m);
@ -11,22 +16,18 @@ void ShortestPath(MatGrath &G,int v,int w); //Dijkstra算法求最短
void Ppath(MatGrath &G,int path[],int w,int v); //前向递归查找路径上的顶点 void Ppath(MatGrath &G,int path[],int w,int v); //前向递归查找路径上的顶点
int Ppath1(MatGrath &G,int path[][MAXV],int v,int w);//前向递归查找路径上的顶点 int Ppath1(MatGrath &G,int path[][MAXV],int v,int w);//前向递归查找路径上的顶点
int ShortestMoney(MatGrath &G,int v,int w); //用floyd算法求最少费用 void ShortestMoney(MatGrath &G,int v,int w); //用floyd算法求最少费用
int menu(void); int menu(void);
int delet(MatGrath &G,int y,int x); int delet(MatGrath &G,int y,int x);
int search(MatGrath &G); //查找某一个城市的信息 int search(MatGrath &G); //查找某一个城市的信息
int addbian(MatGrath &G); //增加城市的边信息 void addbian(MatGrath &G); //增加城市的边信息
int adddian(MatGrath &G); //增加城市的信息 void adddian(MatGrath &G); //增加城市的信息
int modify(MatGrath &G); //修改城市信息 void modify(MatGrath &G); //修改城市信息
int display(MatGrath &G);//输出所有城市信息 int display(MatGrath &G);//输出所有城市信息
int danyuan(MatGrath &G,int d); //求两点之间的最短路径
int Ppath2(MatGrath &G,int path[],int i,int v);
int main() int main()
{ {
int a; //case语句的选择 int a; //case语句的选择
@ -40,25 +41,59 @@ int main()
MatGrath G; MatGrath G;
system("color 1A"); /*修改控制台的颜色信息,改为绿字红底的模式*/ system("color 1A"); /*修改控制台的颜色信息,改为绿字红底的模式*/
CreatGrath(G); CreatGrath(G);
printf(" ■■■■■■■■■■■■■■■■■■■■ \n");
printf(" ■ ■ \n");
printf(" ■ ■■■■■■■■■■■■■■■■ ■ \n"); printf(" ■ ■■■■■■■■■■■■■■■■ ■ \n");
printf(" ■ ■欢迎使用城市公路导航系统■ ■ \n"); printf(" ■ ■欢迎使用城市公路导航系统■ ■ \n");
printf(" ■ ■■■■■■■■■■■■■■■■ ■ \n"); printf(" ■ ■■■■■■■■■■■■■■■■ ■ \n");
printf(" ■ 作者:杨腾泽 ■ \n");
printf(" ■■■■■■■■■■■■■■■■■■■■ \n");
printf("\n"); printf("\n");
printf(" 编号 城市名称\n"); printf(" 编号 城市名称\n");
printf(" 1 烟台市\n"); printf(" 1 济南市\n");
printf(" 2 青岛市\n"); printf(" 2 德州市\n");
printf(" 3 潍坊市\n"); printf(" 3 淄博市\n");
printf(" 4 威海市\n"); printf(" 4 潍坊市\n");
printf(" 5 东营市\n"); printf(" 5 烟台市\n");
printf(" 6 滨州市\n"); printf(" 6 威海市\n");
printf(" 7 德州市\n"); printf(" 7 青岛市\n");
printf(" 8 聊城市\n"); printf(" 8 日照市\n");
printf(" 9 菏泽市\n"); printf(" 9 临沂市\n");
printf(" 10 泰安市\n"); printf(" 10 济宁市\n");
printf(" 11 泰安市\n");
printf(" 12 滨州市\n");
printf(" 13 菏泽市\n");
printf(" 14 即墨市\n");
printf(" 15 胶州市\n");
printf(" 16 胶南市\n");
printf(" 17 诸城市\n");
printf(" 18 高密市\n");
printf(" 19 安丘市\n");
printf(" 20 莒县\n");
printf(" 21 平度市\n");
printf(" 22 莱西市\n");
printf(" 23 莱阳市\n");
printf(" 24 海阳市\n");
printf(" 25 乳山市\n");
printf(" 26 文登市\n");
printf(" 27 荣成市\n");
printf(" 28 牟平市\n");
printf(" 29 蓬莱市\n");
printf(" 30 栖霞市\n");
printf(" 31 莱州市\n");
printf(" 32 招远市\n");
printf(" 33 龙口市\n");
printf(" 34 昌邑市\n");
printf(" 35 昌乐\n");
printf(" 36 孝光市\n");
printf(" 37 青州市\n");
printf(" 38 临朐\n");
printf(" 39 沂水\n");
printf(" 40 广饶\n");
printf(" 41 东营市\n");
printf(" 42 沂源\n");
printf(" 43 恒台\n");
printf(" 44 博兴\n");
printf(" 45 博山\n");
printf(" 46 沂南\n");
printf(" 47 蒙阴\n");
printf(" 48 莱芜市\n");
while(a!=9) while(a!=9)
{ {
a=menu(); a=menu();
@ -86,7 +121,7 @@ int main()
modify(G); modify(G);
break; break;
case 4: case 4:
printf("1-增加边2-增加点"); printf("1-增加边,2-增加点");
scanf("%d",&c); scanf("%d",&c);
if(c==1) if(c==1)
@ -98,20 +133,15 @@ int main()
display(G); display(G);
break; break;
case 6: case 6:
scanf("%d",&d);
danyuan(G,d);
break;
case 7:
scanf("%d",&m); scanf("%d",&m);
DFS(G,m); DFS(G,m);
break; break;
case 8: case 7:
scanf("%d",&y); scanf("%d",&y);
scanf("%d",&x); scanf("%d",&x);
delet(G,y,x); delet(G,y,x);
break; break;
case 9: case 8:
printf("欢迎使用,再见!\n"); printf("欢迎使用,再见!\n");
exit(0); exit(0);
break; break;

@ -15,18 +15,17 @@
printf(" ┏━━━━━━━━━━━━━━━━━━━━┓\n"); printf(" ┏━━━━━━━━━━━━━━━━━━━━┓\n");
printf(" ┃ 1.选择出发点和目的地 ┃\n"); printf(" ┃ 1.选择出发点和目的地 ┃\n");
printf(" ┃ 2.查看景点信息 ┃\n"); printf(" ┃ 2.查看城市信息 ┃\n");
printf(" ┃ 3.修改城市信息 ┃\n"); printf(" ┃ 3.修改城市信息 ┃\n");
printf(" ┃ 4.增加景点信息 ┃\n"); printf(" ┃ 4.增加城市信息 ┃\n");
printf(" ┃ 5.输出所有城市信息 ┃\n"); printf(" ┃ 5.输出所有城市信息 ┃\n");
printf(" ┃ 6.输出单源路径 ┃\n"); printf(" ┃ 6.DFS遍历输出 ┃\n");
printf(" ┃ 7.DFS遍历输出 ┃\n"); printf(" ┃ 7.删除节点 ┃\n");
printf(" ┃ 8.删除节点 ┃\n"); printf(" ┃ 8.退出系统 ┃\n");
printf(" ┃ 9.退出系统 ┃\n");
printf(" ┗━━━━━━━━━━━━━━━━━━━━┛\n"); printf(" ┗━━━━━━━━━━━━━━━━━━━━┛\n");
printf(" 请输入您的选择\n"); printf(" 请输入您的选择\n");
scanf("%d",&c); scanf("%d",&c);
if(c==1||c==2||c==3||c==4||c==5||c==6||c==7||c==8||c==9) if(c==1||c==2||c==3||c==4||c==5||c==6||c==7||c==8)
flag=0; flag=0;
} while(flag); } while(flag);
return c; return c;

@ -1,194 +0,0 @@
#include"type.h"
/***********************
floyd
***********************/
//Dijkstra算法
void Ppath(MatGrath &G,int path[],int w,int v) //前向递归查找路径上的顶点
{
int k;
k=path[w];
if (k==v) return; //找到了起点则返回
Ppath(G,path,k,v); //找顶点k的前一个顶点
printf("%s->",G.vexs[k].sight); //输出顶点k
}
int ShortestPath(MatGrath &G,int v,int w)//求两点之间的最短路径
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u;
for (i=0; i<G.vexnum; i++)
{
dist[i]=G.arc[v][i].length; //距离初始化
s[i]=0; //s[]置空
if (G.arc[v][i].length<INF) //路径初始化
path[i]=v; //v到i有边
else
path[i]=-1; //v到i没有边置顶点i的前一个顶点为-1
}
s[v]=1;
path[v]=0; //源点编号v放入s中
for (i=0; i<G.vexnum; i++) //循环直到所有顶点的最短路径都求出
{
mindis=INF; //mindis置最小长度初值
for (j=0; j<G.vexnum; j++) //选取不在s中且具有最小距离的顶点u
if (s[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1; //顶点u加入s中
for (j=0; j<G.vexnum; j++) //修改不在s中的顶点的距离
if (s[j]==0)
if (G.arc[u][j].length<INF && dist[u]+G.arc[u][j].length<dist[j])
{
dist[j]=dist[u]+G.arc[u][j].length;
path[j]=u;
}
}
if (s[w]==1)
{
printf(" 从%s到%s的最短路径长度为:%d米\t路径为:",G.vexs[v].sight,G.vexs[w].sight,dist[w]);
printf("%s->",G.vexs[v].sight); //输出路径上的起点
Ppath(G,path,w,v); //输出路径上的中间点
printf("%s\n",G.vexs[w].sight); //输出路径上的终点
}
if(s[w]==0)
printf("从%d到%d不存在路径\n",v,w);
}
/***********************
floyd
***********************/
//Floyd算法
int Ppath1(MatGrath &G,int path[][MAXV],int v,int w) //前向递归查找路径上的顶点
{
int k;
k=path[v][w];
if (k==-1) return 0; //找到了起点则返回
Ppath1(G,path,v,k); //找顶点i的前一个顶点k
printf("%s->",G.vexs[k].sight);
Ppath1(G,path,k,w); //找顶点k的前一个顶点j
}
void ShortestMoney(MatGrath &G,int v,int w)//求花费最少的路径
{
int A[MAXV][MAXV],path[MAXV][MAXV];
int i,j,k;
for (i=0; i<G.vexnum; i++)
for (j=0; j<G.vexnum; j++)
{
A[i][j]=G.arc[i][j].money;
path[i][j]=-1; //i到j没有边
}
for (k=0; k<G.vexnum; k++)
{
for (i=0; i<G.vexnum; i++)
for (j=0; j<G.vexnum; j++)
if (A[i][j]>A[i][k]+A[k][j])
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
if (A[v][w]==INF)
{
if (v!=w)
printf("从%d到%d没有路径\n",v,w);
}
else
{
printf(" 从%s到%s路径费用:%d元人民币 路径:",G.vexs[v].sight,G.vexs[w].sight,A[v][w]);
printf("%s->",G.vexs[v].sight); //输出路径上的起点
Ppath1(G,path,v,w); //输出路径上的中间点
printf("%s\n",G.vexs[w].sight); //输出路径上的终点
}
}
/***********************
Dijkstra
***********************/
//Dijkstra算法求单源路径
int Ppath2(MatGrath &G,int path[],int i,int v) //前向递归查找路径上的顶点
{
int k;
k=path[i];
if (k==v)
return k; //找到了起点则返回
Ppath2(G,path,k,v); //找顶点k的前一个顶点
printf("%s->",G.vexs[k].sight);//输出顶点k
}
int danyuan(MatGrath &G,int v)//求两点之间的最短路径
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u;
for (i=1; i<=G.vexnum; i++)
{
dist[i]=G.arc[v][i].length; //距离初始化
s[i]=0; //s[]置空
if (G.arc[v][i].length<INF) //路径初始化
path[i]=v;
else
path[i]=-1;
}
s[v]=1;
path[v]=0; //源点编号v放入s中
for (i=1; i<=G.vexnum; i++) //循环直到所有顶点的最短路径都求出
{
mindis=INF; //mindis置最小长度初值
for (j=1; j<=G.vexnum; j++) //选取不在s中且具有最小距离的顶点u
if (s[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1; //顶点u加入s中
for (j=1; j<=G.vexnum; j++) //修改不在s中的顶点的距离
if (s[j]==0)
if (G.arc[u][j].length<INF && dist[u]+G.arc[u][j].length<dist[j])
{
dist[j]=dist[u]+G.arc[u][j].length;
path[j]=u;
}
}
for(i=1; i<=G.vexnum; i++)
if (s[i]==1&&v!=i)
{
printf(" 从%s到%s的最短路径长度为:%d米\t路径为:",G.vexs[v].sight,G.vexs[i].sight,dist[i]);
printf("%s->",G.vexs[v].sight); //输出路径上的起点
Ppath2(G,path,i,v); //输出路径上的中间点
printf("%s\n",G.vexs[i].sight); //输出路径上的终点
}
}

@ -0,0 +1,74 @@
#include"type.h"
//Dijkstra算法
void Ppath(MatGrath &G,int path[],int w,int v) //前向递归查找路径上的顶点
{
int k;
k=path[w];
if (k==v) return; //找到了起点则返回
Ppath(G,path,k,v); //找顶点k的前一个顶点
printf("%s->",G.vexs[k].sight); //输出顶点k
}
void ShortestPath(MatGrath &G,int v,int w)//求两点之间的最短路径
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u;
for (i=0; i<G.vexnum; i++)
{
dist[i]=G.arc[v][i].length; //距离初始化
s[i]=0; //s[]置空
if (G.arc[v][i].length<INF) //路径初始化
path[i]=v; //v到i有边
else
path[i]=-1; //v到i没有边置顶点i的前一个顶点为-1
}
s[v]=1;
path[v]=0; //源点编号v放入s中
for (i=0; i<G.vexnum; i++) //循环直到所有顶点的最短路径都求出
{
mindis=INF; //mindis置最小长度初值
for (j=0; j<G.vexnum; j++) //选取不在s中且具有最小距离的顶点u
if (s[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1; //顶点u加入s中
for (j=0; j<G.vexnum; j++) //修改不在s中的顶点的距离
if (s[j]==0)
if (G.arc[u][j].length<INF && dist[u]+G.arc[u][j].length<dist[j])
{
dist[j]=dist[u]+G.arc[u][j].length;
path[j]=u;
}
}
if (s[w]==1)
{
printf(" 从%s到%s的最短路径长度为:%d米\t路径为:",G.vexs[v].sight,G.vexs[w].sight,dist[w]);
printf("%s->",G.vexs[v].sight); //输出路径上的起点
Ppath(G,path,w,v); //输出路径上的中间点
printf("%s\n",G.vexs[w].sight); //输出路径上的终点
}
if(s[w]==0)
printf("从%d到%d不存在路径\n",v,w);
}
/***********************
Dijkstra
***********************/

@ -1,28 +1,27 @@
#include <stdio.h> #pragma once
#define NO 30 #ifndef _TEST_H_
#define _TEST_H_
#define M 30
#define MAXV 100 //最大顶点个数 #define MAXV 100 //最大顶点个数
#define INF 32767 //INF表示∞ #define INF 32767 //INF表示∞
typedef struct
{
int length;//边的长度,既两个地点之的长
int money;
}ArcCell; //定义边的类型
typedef struct struct VertexType
{ int no; //顶点的编号 { int bianhao; //顶点的编号
char sight[10]; //地点 char sight[10]; //地点
char introduction[100]; //地点的介绍 }; //定义顶点的类型
}VertexType; //定义顶点的类型
struct ArcCell
{
int length;//边的长度,既两个地点之的长
}; //定义边的类型
typedef struct struct MatGrath
{ {
int vexnum; //顶点数 int vexnum; //顶点数
int arcnum; //边数 int arcnum; //边数
VertexType vexs[NO]; //在图结构体中调用点的结构体 VertexType vexs[M]; //在图结构体中调用点的结构体
ArcCell arc[NO][NO]; //在图结构体中调用边的结构体 ArcCell arc[M][M]; //在图结构体中调用边的结构体
}MatGrath; };
#endif
Loading…
Cancel
Save