数据结构课程设计-旅游景点咨询系统的设计与实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
旅游景点咨询系统的设计与实现
一、需求分析
1、问题描述
创建一个至少有15个点的无向网表示的某个旅游景点的导游图。
顶点代表景点,类型为字符串(例如,泰山导游图:“天地广场门”,“十八盘”,“冯玉祥墓",“桃花峪门",“中天门”,“南天门”,“玉皇顶”等),弧表示两个景点之间可以直达,弧上的权值表示两个景点之间的路程(公里数),弧上还有到达方法的信息(有步行和索道两种)。
建立一个游客咨询系统。
2、基本要求
a.创建图的存储结构。
b。
输入两个景点名,就可以得到从一个景点到达另一个景点的所有简单路径、相应路径的路程公里数、行走的方法(每一段是步行,还是坐索道).
c.输入两个景点名,就可以得到其最短路径,即:路程最短的行进方法;如果两者无路径可通,就得出“两景点不可达的信息"。
二、概要设计
1。
数据结构
本程序需要用到两个结构体,分别为ArcCell和MGraph.
2.程序模块
本程序包含两个模块,一个是实现功能的函数的模块,另一个是主函数模块.
系统子程序及功能设计
本系统共有七个子程序,分别是:
int LocateVex(MGraph G,VertexType u)//得到顶点u的序号
void CreateDN(MGraph *G)//建立景点间的无向网
VertexType*GetVex(MGraph G,int v)//根据顶点序号返回顶点值int FirstAdjVex(MGraph G,VertexType v)//返回v的第一个邻接顶点的序号
int NextAdjVex(MGraph G,VertexType v,VertexType w)//返回v的(相对于w的)下一个邻接顶点的序号
void Simpleway(MGraph&m,char *str,char *buf)//求任意两个景点之间的所有简单路径
int Minway(MGraph&m,char *str,char *buf)//求两顶点间的最短路径
3.各模块之间的调用关系以及算法设计
函数CreateDN调用函数LocateVex
函数Simpleway调用函数LocateVex
函数Minway调用函数LocateVex,GetVex,FirstAdjVex,NextAdjVex 主函数调用函数CreateDN,Simpleway,Minway.
三、详细设计
1。
数据类型定义
typedef struct
{
VRType adj;
int info;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
VertexType vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vexnum,arcnum;
}MGraph;
2。
系统主要子程序详细设计
a.
void CreateDN(MGraph *G)
{/*采用数组(邻接矩阵)表示法,构造有向网G */
int i,j,k,w,c;
char s[MAX_INFO],*info;
VertexType va,vb;
printf("请输入景点个数以及景点间所有路径的个数(以空格隔开)”);
scanf(”%d %d",&(*G)。
vexnum,&(*G).arcnum);
printf("请输入%d个景点:\n",(*G)。
vexnum);
for(i=0;i<(*G)。
vexnum;++i) /*构造顶点向量*/
scanf("%s",(*G).vexs[i]);
for(i=0;i〈(*G).vexnum;++i) /* 初始化邻接矩阵*/
for(j=0;j〈(*G)。
vexnum;++j)
{
(*G)。
arcs[i][j]。
adj=INFINITY;/* 网*/
(*G)。
arcs[i][j].info=NULL;
}
printf(”请输入%d条景点间的路径,路径间的路程权值以及路径间到达方式(以0或1来表示到达方式,步行:0,索道:1,如:光明顶迎客松30 1):\n",(*G)。
arcnum);
for(k=0;k<(*G).arcnum;++k)
{
scanf("%s%s%d%d*c",va,vb,&w,&c);/* %*c吃掉回车符*/
i=LocateVex(*G,va);
j=LocateVex(*G,vb);
(*G)。
arcs[i][j].adj=(*G).arcs[j][i].adj=w;/* 有向网*/
(*G)。
arcs[i][j]。
info=(*G)。
arcs[j][i].info=c; /* 有向*/
}
}
b.
void Simpleway(MGraph&m,char *str,char *buf)/*求任意两个景点之间的所有简单路径*/
{
for(int i=0;i〈m。
vexnum;i++)
{
visited[i]=false;
}
int x=LocateVex(m,str);
int y=LocateVex(m,buf);
/*从x出发到y*/
stack<int>s;
s.push(x);
visited[x]=true;
int i=0;
int z=0;//表示没有找到这两个点之间有路径
while(!s。
empty())
{
int flag=0;
//取栈顶元素
int t=s。
top();
for(;i〈m.vexnum;i++)
{
if(m.arcs[t][i]。
adj != INFINITY &&visited[i]==false)
{
s.push(i);
flag=1;
visited[i]=true;
/*找到简单路径*/
if(s.top()==y)//到达终点
{
z=1;//找到这样的路径
cout<<"一条简单路径为:”〈〈endl;
{
stack〈int>s2;//建立一个临时的栈
//创建一个数组存放路径下标
int *way=new int[s。
size()];
int count=0;
while(!s.empty())
{
s2.push(s。
top());
s。
pop();
}
//还原s同时输出路径
while(!s2.empty())
{
cout〈<m.vexs[s2.top()]〈<” ";
way[count++]=s2.top();
s。
push(s2。
top());
s2.pop();
}
//计算路径长度,给出到达的方式
{
int num=0;
cout〈〈”到达方式:”;
for(int k=0;k<s.size()—1;k++)
{
int x1=LocateVex(m,m.vexs[way[k]]);
int y1=LocateVex(m,m.vexs[way[k+1]]);
num+=m。
arcs[x1][y1]。
adj;
if(m.arcs[x1][y1].info==0)
cout<<"步行"<<" ”;
else
cout〈<”索道”〈<" ”;
}
cout<〈"路程:"〈<num<〈endl;
}
}
cout〈<endl;
{
//出栈
int p=s。
top();
visited[p]=false;
s。
pop();
//从p开始接着访问后面的邻接点
i=p+1;
break;
}
}
//跳出本次循环
i=0;
break;
}
}
if(flag==0)
{
//出栈
int p=s。
top();
visited[p]=false;
s。
pop();
//从p开始接着访问后面的邻接点
i=p+1;
}
}
if(z==0)
{
cout<<”两景点不可达"<〈endl;
}
}
c.
int Minway(MGraph&m,char *str,char *buf)//求两顶点间的最短路径{
int x=LocateVex(m,str);
int y=LocateVex(m,buf);
//分配路径相关信息的存储空间
int **road=new int*[m。
vexnum];
for(int i=0;i〈m.vexnum;i++)
{
road[i]=new int[m.vexnum];
}
//初始化
for(int i=0;i〈m。
vexnum;i++)
{
for(int j=0;j<m。
vexnum;j++)
{
if(j==0)
{
road[i][j]=x;
}
else
{
road[i][j]=-1;
}
}
}
for(int i=0;i<m.vexnum;i++)
{
//while(find_s[x]==true)
find_s[i]=false;
length[i]=m.arcs[x][i]。
adj;
if(m.arcs[x][i]。
adj!=INFINITY)
{
road[i][1]=i;
}
}
find_s[x]=true;
length[x]=0;
rigth_length[x]=0;
for(int j=1;j〈m。
vexnum;j++)
{
int pose=find_min_length(m,length);
{
int z=0;
//记录找到它的路径
while(road[pose][z]!=—1&&z<=m.vexnum)
{
z++;
}
}
//cout〈〈"min_length=”<〈length[pose]<<endl;
rigth_length[pose]=length[pose];
//将路径最短的关联的另一个顶点加入已找到路径的数组中
find_s[pose]=true;
//更新最短路径
for(int i=0;i〈m。
vexnum;i++)
{
//i点还没有找到最短路径
if(find_s[i]==false &&m。
arcs[pose][i]。
adj + length[pose]〈length[i])
{
length[i]=m.arcs[pose][i].adj + length[pose];
{
//记录中间节点
int z=0;
//记录找到它的路径
while(road[pose][z]!=—1)
{
z++;
}
/*移位再插入,用pose更新*/
//(1)复制
for(int k=0;k<z;k++)
{
road[i][k]=road[pose][k];
}
road[i][z]=i;
}
}
}
}
cout〈〈endl;
if(road[y][1]==—1)
{
cout〈<"两景点不可达”〈〈endl;
return —1;
}
else
{
cout<〈"最短路径为:";
int count=0;
while(road[y][count]!=-1 &&count〈m.vexnum)
{
cout<<m.vexs[road[y][count]]<<" ";
count++;
}
cout<<" 到达方式:";
for(int i=0;i<count-1;i++)
{
int x1=LocateVex(m,m。
vexs[road[y][i]]);
int y1=LocateVex(m,m.vexs[road[y][i+1]]);
if(m。
arcs[x1][y1].info==0)
cout〈<”步行"<<”";
else
cout<〈”索道"<<" ”;
}
cout<〈endl;
return rigth_length[y];
}
}
四、测试与分析
1.建立旅游景点咨询系统,根据提示依次输入景点,路径,以及到达方式。
2。
求两个景点间的所有简单路径
在主菜单下选2,并输入任意两个景点名称,可以得到这两个景点间的所有简单路径。
3.求两个顶点间的最短路径
在主菜单下选3,并输任意的两个景点,可以得到这两个景点间的最短路径,输出最短路径并以此输出到达方式.
4.退出系统
退出程序。
五、附录
1.旅游景点咨询系统.h
#include<iostream>
#include<string〉
#include<stack>
using namespace std;
#define MAX_NAME 50 /* 顶点字符串的最大长度+1 */
#define MAX_INFO 50 /* 相关信息字符串的最大长度+1 */
typedef int VRType;
typedef char VertexType[MAX_NAME];
#define INFINITY 10000
#define MAX_VERTEX_NUM 20
typedef struct
{
VRType adj;
int info;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
VertexType vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vexnum,arcnum;
}MGraph;
int LocateVex(MGraph G,VertexType u)
{ /* 初始条件:图G存在,u和G中顶点有相同特征*/
/*操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回—1 */ int i;
for(i=0;i〈G.vexnum;++i)
if(strcmp(u,G。
vexs[i])==0)
return i;
return —1;
}
void CreateDN(MGraph *G)
{/*采用数组(邻接矩阵)表示法,构造有向网G */
int i,j,k,w,c;
char s[MAX_INFO],*info;
VertexType va,vb;
printf("请输入景点个数以及景点间所有路径的个数(以空格隔开)");
scanf("%d %d",&(*G)。
vexnum,&(*G).arcnum);
printf("请输入%d个景点:\n",(*G)。
vexnum);
for(i=0;i<(*G)。
vexnum;++i)/* 构造顶点向量*/
scanf("%s",(*G).vexs[i]);
for(i=0;i〈(*G).vexnum;++i) /*初始化邻接矩阵*/
for(j=0;j〈(*G).vexnum;++j)
{
(*G)。
arcs[i][j]。
adj=INFINITY;/* 网*/
(*G)。
arcs[i][j]。
info=NULL;
}
printf("请输入%d条景点间的路径,路径间的路程权值以及路径间到达方式(以0或1来表示到达方式,步行:0,索道:1,如:光明顶迎客松30 1): \n",(*G)。
arcnum);
for(k=0;k〈(*G).arcnum;++k)
{
scanf(”%s%s%d%d*c”,va,vb,&w,&c);/* %*c吃掉回车符*/
i=LocateVex(*G,va);
j=LocateVex(*G,vb);
(*G).arcs[i][j]。
adj=(*G).arcs[j][i].adj=w;/* 有向网*/
(*G)。
arcs[i][j].info=(*G)。
arcs[j][i].info=c;/*有向*/
}
}
VertexType* GetVex(MGraph G,int v)
{/*初始条件:图G存在,v是G中某个顶点的序号。
操作结果:返回v 的值*/
if(v>=G.vexnum||v<0)
exit(0);
return &G。
vexs[v];
}
int FirstAdjVex(MGraph G,VertexType v)
{ /* 初始条件: 图G存在,v是G中某个顶点*/
/*操作结果: 返回v的第一个邻接顶点的序号.若顶点在G中没有邻接顶点,则返回—1 */
int i,j=0,k;
k=LocateVex(G,v);/* k为顶点v在图G中的序号*/
j=INFINITY;
for(i=0;i<G.vexnum;i++)
if(G。
arcs[k][i].adj!=j)
return i;
return —1;
}
int NextAdjVex(MGraph G,VertexType v,VertexType w)
{/* 初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点*/ /* 操作结果: 返回v的(相对于w的)下一个邻接顶点的序号, */
/*若w是v的最后一个邻接顶点,则返回-1 */
int i,j=0,k1,k2;
k1=LocateVex(G,v);/* k1为顶点v在图G中的序号*/
k2=LocateVex(G,w); /*k2为顶点w在图G中的序号*/
j=INFINITY;
for(i=k2+1;i<G。
vexnum;i++)
if(G。
arcs[k1][i]。
adj!=j)
return i;
return —1;
}
bool visited[MAX_NAME];
void Simpleway(MGraph&m,char *str,char *buf)/*求任意两个景点之间的所有简单路径*/
{
for(int i=0;i〈m.vexnum;i++)
{
visited[i]=false;
}
int x=LocateVex(m,str);
int y=LocateVex(m,buf);
/*从x出发到y*/
stack<int>s;
s.push(x);
visited[x]=true;
int i=0;
int z=0;//表示没有找到这两个点之间有路径
while(!s。
empty())
{
int flag=0;
//取栈顶元素
int t=s.top();
for(;i〈m.vexnum;i++)
{
if(m.arcs[t][i].adj != INFINITY &&visited[i]==false)
{
s.push(i);
flag=1;
visited[i]=true;
/*找到简单路径*/
if(s.top()==y)//到达终点
{
z=1;//找到这样的路径
cout〈〈"一条简单路径为:"〈〈endl;
{
stack<int〉s2;//建立一个临时的栈
//创建一个数组存放路径下标
int *way=new int[s.size()];
int count=0;
while(!s.empty())
{
s2。
push(s.top());
s.pop();
}
//还原s同时输出路径
while(!s2。
empty())
{
cout<<m。
vexs[s2.top()]〈〈" ";
way[count++]=s2.top();
s.push(s2。
top());
s2.pop();
}
//计算路径长度,给出到达的方式
{
int num=0;
cout<<" 到达方式:”;
for(int k=0;k〈s。
size()-1;k++)
{
int x1=LocateVex(m,m.vexs[way[k]]);
int y1=LocateVex(m,m。
vexs[way[k+1]]);
num+=m.arcs[x1][y1].adj;
if(m.arcs[x1][y1].info==0)
cout〈<”步行”<<" ";
else
cout<〈"索道”<<””;
}
cout<<”路程:”<〈num<<endl;
}
}
cout〈<endl;
{
//出栈
int p=s.top();
visited[p]=false;
s。
pop();
//从p开始接着访问后面的邻接点
i=p+1;
break;
}
}
//跳出本次循环
i=0;
break;
}
}
if(flag==0)
{
//出栈
int p=s。
top();
visited[p]=false;
s.pop();
//从p开始接着访问后面的邻接点
i=p+1;
}
}
if(z==0)
{
cout<<”两景点不可达"〈〈endl;
}
}
bool find_s[MAX_NAME];//标记是否找到最短路径
int length[MAX_NAME];//记录最短路径
int rigth_length[MAX_NAME];
int find_min_length(MGraph &m,int *a)
{
int x=0;
while(find_s[x]==true)
{
x++;
}
for(int i=1;i〈m.vexnum;i++)
{
if(a[x]>a[i]&& find_s[i]==false)
{
x=i;
}
}
return x;
}
int Minway(MGraph&m,char *str,char *buf)//求两顶点间的最短路径{
int x=LocateVex(m,str);
int y=LocateVex(m,buf);
//分配路径相关信息的存储空间
int **road=new int*[m.vexnum];
for(int i=0;i<m。
vexnum;i++)
{
road[i]=new int[m。
vexnum];
}
//初始化
for(int i=0;i〈m.vexnum;i++)
{
for(int j=0;j<m。
vexnum;j++)
{
if(j==0)
{
road[i][j]=x;
}
else
{
road[i][j]=—1;
}
}
}
for(int i=0;i〈m.vexnum;i++)
{
//while(find_s[x]==true)
find_s[i]=false;
length[i]=m。
arcs[x][i]。
adj;
if(m。
arcs[x][i].adj!=INFINITY)
{
road[i][1]=i;
}
}
find_s[x]=true;
length[x]=0;
rigth_length[x]=0;
for(int j=1;j<m.vexnum;j++)
{
int pose=find_min_length(m,length);
{
int z=0;
//记录找到它的路径
while(road[pose][z]!=—1&&z〈=m.vexnum)
{
z++;
}
}
//cout<〈”min_length=”<〈length[pose]〈〈endl;
rigth_length[pose]=length[pose];
//将路径最短的关联的另一个顶点加入已找到路径的数组中
find_s[pose]=true;
//更新最短路径
for(int i=0;i<m。
vexnum;i++)
{
//i点还没有找到最短路径
if(find_s[i]==false && m。
arcs[pose][i].adj + length[pose]< length[i])
{
length[i]=m。
arcs[pose][i]。
adj + length[pose];
{
//记录中间节点
int z=0;
//记录找到它的路径
while(road[pose][z]!=-1)
{
z++;
}
/*移位再插入,用pose更新*/
//(1)复制
for(int k=0;k〈z;k++)
{
road[i][k]=road[pose][k];
}
road[i][z]=i;
}
}
}
}
cout<〈endl;
if(road[y][1]==—1)
{
cout〈<"两景点不可达”〈〈endl;
return —1;
}
else
{
cout〈〈"最短路径为:";
int count=0;
while(road[y][count]!=-1 &&count〈m.vexnum) {
cout〈〈m.vexs[road[y][count]]<〈" ";
count++;
}
cout〈<”到达方式:”;
for(int i=0;i〈count-1;i++)
{
int x1=LocateVex(m,m.vexs[road[y][i]]);
int y1=LocateVex(m,m。
vexs[road[y][i+1]]);
if(m。
arcs[x1][y1]。
info==0)
cout<<”步行”<〈”";
else
cout<<”索道”<<" ";
}
cout〈〈endl;
return rigth_length[y];
}
}
2。
旅游景点咨询系统。
cpp(主函数)
#include”旅游景点咨询系统.h"
int main()
{
MGraph G;
VertexType a,b;
int ch;
while(1)
{
cout〈<"-—-—-——------—--旅游景点咨询系统---———-———-—-—--"<<endl;
cout〈<”1。
建立景点导游图"〈〈endl;
cout<<" 2。
两个景点间的所有简单路径”<〈endl;
cout〈〈” 3.两个景点间的最短路径”〈〈endl;
cout〈〈”4。
退出"〈<endl;
cout〈〈endl;
cout〈<"请输入功能编号:"〈〈endl;
cin>〉ch;
if(ch〉4 || ch<1)
{
do{
cout〈<"输入有误,请重新输入!”〈<endl;
cin〉〉ch;
}while(ch〈=3&&ch〉=1);
}
switch(ch)
{
case 1:
{
cout〈<”建立景点导游图”〈〈endl;
CreateDN(&G);
break;
}
case 2:
{
cout〈<”两个景点间的所有简单路径"〈<endl;
cout<<"请输入两个景点(以空格隔开)”<〈endl;
cin〉〉a〉>b;
Simpleway(G,a,b);
break;
}
case 3:
{
cout〈<"两个景点间的最短路径"〈<endl;
cout<<”请输入两个景点(以空格隔开)"<〈endl;
cin〉>a>〉b;
Minway(G,a,b);
break;
}
case 4:exit(0);
default:
break;
}
}
return 0;
}六、用户手册
运行旅游景点咨询系统.exe,即可运行该旅游景点咨询系统并完成相应的功能。