1、问题分析和任务定义
【问题描述】
设计一个校园导游程序,为来访的客人提供各种信息查询服务
【基本要求】
设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息
为来访客人提供图中任意景点相关信息的查询
为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径
【实现提示】
一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向网顶点和边均含有相关信息
【测试数据】
以江苏科技大学长山校区为例:
2、数据结构的选择和概要设计
(1)使用的数据结构为:无向带权图,定义三个结构体边、顶点、图。
(2)主要算法:迪杰斯特拉算法、弗洛伊德算法
可能的数据结构设计:
算法细解:
迪杰斯特拉算法:设置一个集合S存放已经找到最短路径的顶点,S的初始状态只包含源点v,对vi∈V-S,假设从源点v到vi的有向边为最短路径。以后每求得一条最短路径v, …, vk,就将vk加入集合S中,并将路径v, …, vk , vi与原来的假设相比较,取路径长度较小者为最短路径。重复上述过程,直到集合V中全部顶点加入到集合S中。
弗洛伊德算法:对于从vi到vj的弧,进行n次试探:首先考虑路径vi,v0,vj是否存在,如果存在,则比较vi,vj和vi,v0,vj的路径长度,取较短者为从vi到vj的中间顶点的序号不大于0的最短路径。在路径上再增加一个顶点v1,依此类推,在经过n次比较后,最后求得的必是从顶点vi到顶点vj的最短路径。
3、详细设计和编码
主要设计如下:
Step01:
初始化图的邻接矩阵,邻接矩阵是对称矩阵,对称赋值(无向图需要对称赋值)例如
strcpy(c.vexs[1].name,"北门");strcpy(c.vexs[1].super_introduction,"\n北门:从北面进出\n");
strcpy(c.vexs[1].introduction,"离学院楼较近");
strcpy(c.vexs[2].name,"海韵湖
Step02:
查找景点在图中的序号int locatevex(mgraph c,int v)//locatevex
Step03:
查找并输出序号为m,n景点间的长度不超过8个景点的路径
void path(mgraph c,int m,int n,int k)
Step04:
查找两景点间的景点的所有路径 int allpath(mgraph c)
Step05:
迪杰斯特拉算法,求出一个景点到其他景点间的最短路径
void shortestpath_dij(mgraph c)
4、测试结果及其分析
5、用户使用说明
按照代码提示使用即可
6、参考文献
dijkstra算法详解(迪杰斯特拉算法)简单易懂 - unique_pursuit - 博客园
大二数据结构实验之校园导游咨询程序(C++)_wying_0的博客-CSDN博客
https://blog.csdn.net/DEAR_CXN/article/details/86555936
7、附录(部分)
#include<stdio.h>//无向带权图
#include<stdlib.h>
#include<string.h>
#define Infinity 2000//表示无穷大
#define MaxVertexNum 20
#define MAX 40
#define key 11//key为顶点个数
typedef struct arcell//边的权值信息
{ int adj;//权值
}arcell,adjmatrix[MaxVertexNum][MaxVertexNum];//图的邻接矩阵类型
typedef struct vexsinfo//顶点信息
{ int position;//景点的编号
char name[32];//景点的名称
char introduction[256];//景点的介绍
char super_introduction[512];//景点的详细介绍
}vexsinfo;
typedef struct mgraph//图结构信息
{ vexsinfo vexs[MaxVertexNum];//顶点向量(数组)
adjmatrix arcs;//邻接矩阵
int vexnum,arcnum;//顶点数和边数
}mgraph;
//全局变量
mgraph campus; //图变量(大学校园)
int d[30];
int visited[30];
int shortest[MaxVertexNum][MaxVertexNum];//定义全局变量存储最小路径
int pathh[MaxVertexNum][MaxVertexNum];//定义存储路径
mgraph initgraph()
{ int i=0,j=0;
mgraph c;
c.vexnum=11;//顶点个数
c.arcnum=20;//边的个数
for(i=1;i<=key;i++)//依次设置顶点编号
c.vexs[i].position=i;
//依次输入顶点信息
strcpy(c.vexs[1].name,"北门");strcpy(c.vexs[1].super_introduction,"\n北门:从北面进出\n");
strcpy(c.vexs[1].introduction,"离学院楼较近");
strcpy(c.vexs[2].name,"海韵湖");strcpy(c.vexs[2].super_introduction,"\n海韵湖:一个湖\n");
strcpy(c.vexs[2].introduction,"湖很宽");
strcpy(c.vexs[3].name,"文理大楼");strcpy(c.vexs[3].super_introduction,"\n文理大楼:授课地点之一");
strcpy(c.vexs[3].introduction,"校内独特建筑");
strcpy(c.vexs[4].name,"经世楼");strcpy(c.vexs[4].super_introduction,"\n经世楼:授课地点中的一个\n");
strcpy(c.vexs[4].introduction,"有哼多教室");
strcpy(c.vexs[5].name,"图书馆");strcpy(c.vexs[5].super_introduction,"\n图书馆:繁荣了文化氛围。\n");
strcpy(c.vexs[5].introduction,"读书圣地");
strcpy(c.vexs[6].name,"西宿舍");strcpy(c.vexs[6].super_introduction,"\n西宿舍:男生多\n");
strcpy(c.vexs[6].introduction,"一片宿舍");
strcpy(c.vexs[7].name,"西食堂");strcpy(c.vexs[7].super_introduction,"\n西食堂:物美价廉\n");
strcpy(c.vexs[7].introduction,"童叟无欺");
strcpy(c.vexs[8].name,"西操场");strcpy(c.vexs[8].super_introduction,"\n西操场:锻炼场地\n");
strcpy(c.vexs[8].introduction,"离西食堂较近");
strcpy(c.vexs[9].name,"文体中心");strcpy(c.vexs[9].super_introduction,"\n文体中心:可以进行多种运动\n");
strcpy(c.vexs[9].introduction,"可以锻炼");
strcpy(c.vexs[10].name,"东操场");strcpy(c.vexs[10].super_introduction,"\n东操场:和西操场差不多\n");
strcpy(c.vexs[10].introduction,"东边的操场");
strcpy(c.vexs[11].name,"东食堂");strcpy(c.vexs[11].super_introduction,"\n东食堂:比西食堂好吃吗?\n");
strcpy(c.vexs[11].introduction,"东边学生光顾");
for(i=1;i<=key;i++)
for(j=1;j<=key;j++)
c.arcs[i][j].adj=Infinity;//先初始化图的邻接矩阵
c.arcs[1][2].adj=45;c.arcs[1][3].adj=70;c.arcs[2][3].adj=45;c.arcs[2][5].adj=45;c.arcs[3][4].adj=30;
c.arcs[3][5].adj=50;c.arcs[3][10].adj=70;c.arcs[4][7].adj=60;c.arcs[4][8].adj=30;c.arcs[5][11].adj=15;
c.arcs[6][7].adj=50;c.arcs[7][8].adj=50;c.arcs[8][9].adj=15;c.arcs[9][10].adj=50;c.arcs[10][11].adj=35;
for(i=1;i<=key;i++)//邻接矩阵是对称矩阵,对称赋值(无向图需要对称赋值)
for(j=1;j<=key;j++)
c.arcs[j][i].adj=c.arcs[i][j].adj;
return c;
}//initgraph
//2.查找景点在图中的序号
int locatevex(mgraph c,int v)//locatevex
{ int i;
for(i=1;i<=c.vexnum;i++)
if(v==c.vexs[i].position) return i;//找到,返回顶点序号i
return -1;//没有找到这个顶点
}
//3.查找并输出序号为m,n景点间的长度不超过8个景点的路径
void path(mgraph c,int m,int n,int k)
{ int s,t=k+1,length=0;//t用于存放路径上下一个顶点对应的d[]数组元素的下标
if(d[k]==n&&k<8)//若d[k]是终点n且景点个数<=8,则输出该路径
{ for(s=0;s<k;s++)//计算路径长度
{
length=length+c.arcs[d[s]][d[s+1]].adj;
}
if(length<=100)//打印路径长度小于定长的路径
{ for(s=0;s<k;s++)//输出该路径。s=0时为起点m
{
printf("%d%s--->",d[s],c.vexs[d[s]].name);
}
printf("%d%s ",d[s],c.vexs[d[s]].name);//输出最后一个景点名(即顶点n的名字,此时s==k)
printf("总路线长为%d米\n\n",length);
}
}
else
{ s=1;
while(s<=c.vexnum)//从第m个顶点,试探所有顶点是否有路径
{ if((c.arcs[d[k]][s].adj<Infinity)&&(visited[s]==0))//顶点m到顶点s有边(权值不为无穷大),且未被访问
{ visited[s]=1;
d[k+1]=s;//存储顶点编号
path(c,m,n,t);
visited[s]=0;//将找到的路径上顶点的访问标志重新设置为0,以用于试探新的路径
}
s++;//试探从下一个顶点s开始是否有到终点的路径
}
}
}