您的当前位置:首页[旅游行业]数据结构旅游区导航图课程设计

[旅游行业]数据结构旅游区导航图课程设计

2023-08-08 来源:飒榕旅游知识分享网


(旅游行业)数据结构旅游区导航图课程设计

《数据结构课程设计》报告

题目 旅游区导游图 专业 计算机科学与技术 班级 (2)班 学生 ###

13旅游区导游图

题目内容 问题描述:

设某个旅游区共有n个旅游景点(n≥10),每个旅游景点都和相邻的m个旅游景点(m≥2,m以(Vi,Vj,d)的形式从键盘输入建立该旅游区的旅游景点图,其中:Vi和Vj表示两个不同的旅游景点,d表示这两个景点之间的道路距离;该旅游景点图采用邻接矩阵存储结构(数组)。

实现要求:

⑴旅游景点图的输出:分别以邻接矩阵、邻接链表的方式输出该旅游景点图。 ⑵相邻景点查询:假设对于每个景点,设置有简易的信息查询,要求能给出与该景点相邻的所有景点(有直接的道路相通)及对应的距离。

⑶景点路线查询:假设对于每个景点,设置有景点路线查询,要求能给出从该景点出发到任一其它景点的最短简单路径及距离。

⑷景点路线综合查询:对于该旅游区的任意两个景点,找出它们之间的最短简单

路径及距离。

⑸最佳旅游路线确定:假设该旅游区的入口也是出口,请确定一条最佳的旅游线路,该线路必须经过所有的旅游景点(有些景点可以重复经过)且走的路最短。 ⑹设计一个菜单,上述操作要求都作为菜单中的主要菜单项。

⒈ 本人完成的工作

完成的工作:首先是用邻接矩阵的存储形式建立无向带权图,然后将邻接矩阵转换为邻接链表,最后用狄克斯特拉函数求出后面的三道有关最短路径的小题,设计主函数。

⒉ 所采用的数据结构

邻接矩阵的数据结构,包括(弧/边的结构定义、图的结构定义) 邻接链表的数据结构,包括(弧/边的结点定义、邻接表头结点定义、图的结构定义)

数据结构的定义

//邻接矩阵结构体 typedefstruct

{charvex1,vex2;/*弧或边所依附的两个顶点*/ intArcVal;/*弧或边的权值*/ }ArcType;/*弧或边的结构定义*/ typedefstruct {

intvexnum,arcnum;/*图的当前顶点数和弧数*/ charvexs[MAXVEX];/*顶点向量*/

intadj[MAXVEX][MAXVEX]; }MGraph;/*图的结构定义*/ //邻接链表结构体

typedefstructANode//弧的结点结构类型 {intadjvex;//该弧的终点位置

intinfo;//该弧的相关信息,这里用于存放权值 structANode*nextarc;//指向下一条弧的指针 }ArcNode;

typedefstructVnode//邻接表头结点的类型 {

chardata;//顶点信息

ArcNode*firstarc;//指向第一条弧 }VNode; typedefstruct {

VNodeAdjList[MAXVEX];

intvexnum,arcnum;//图中顶点数n和边数e }ALGraph;//图的邻接表类型

⒊ 所设计的函数

对于每个主要函数必须给出所采用的算法思想和程序框图;

邻接矩阵和邻接链表初始化函数 MGraph*Init_MGraph()

/*图的初始化*/ {

MGraph*G;

G=(MGraph*)malloc(sizeof(MGraph));

G->vexnum=0;G->arcnum=0;/*初始化顶点数、边数*/ return(G); }

ALGraph*Init_ALGraph() /*图的初始化*/ {

ALGraph*G;

G=(ALGraph*)malloc(sizeof(ALGraph)); G->vexnum=0;

G->arcnum=0;/*初始化顶点数*/ return(G); }

图中顶点定位的函数,判断顶点是否重复输入了 intLocateVex(MGraph*G,charvp)

/*图中顶点的定位,若图中有顶点vp,返回其在顶点数组的下标值*/ { intk;

for(k=0;k<=G->vexnum;k++)

if(G->vexs[k]==vp)return(k); return(-1);/*图中无此顶点*/ } N NY Y

往图中增加顶点的函数

voidAddVertex(MGraph*G,charvp) /*往图的顶点数组中增加顶点*/ { intk,j;

if(G->vexnum>=MAXVEX) printf(\"图中顶点数已达到最多!\\n\"); else {

if(LocateVex(G,vp)==-1) {

k=G->vexnum;G->vexs[G->vexnum++]=vp; for(j=0;jvexnum;j++) {

G->adj[j][k]=INFINITY; G->adj[k][j]=INFINITY;

/*是带权的有向图或无向图*/ } } } } N Y NY

往图的邻接矩阵中添加边(弧) voidAddArc(MGraph*G,ArcType*arc) /*往图的邻接矩阵中添加边(弧)*/ {

intk=0,j=0;

k=LocateVex(G,arc->vex1); j=LocateVex(G,arc->vex2); if(k==-1||j==-1)

printf(\"边或弧的顶点不存在,错误!\\n\"); else {

G->arcnum++;

G->adj[k][j]=arc->ArcVal; G->adj[j][k]=arc->ArcVal;

结束 新增加一个顶点 给k赋值=顶点总数 判断顶点数目是否已经超过最大值 开始 调用函数LocateVex,判断顶点是否有重复 把这个点跟其他所有点建立关系,为INFINITY,表示不存在连通关系

/*是无向图或带权的无向图,需对称赋值*/ } }

输出图的顶点矩阵和邻接矩阵 voidoutput_graphic(MGraph*G) /*输出图的顶点矩阵和邻接矩阵*/ { intk,j;

printf(\"图的顶点如下:\\n\"); for(k=0;kvexnum;k++) printf(\"%4c\printf(\"\\n\\n\");

printf(\"图的邻接矩阵如下:\\n\"); for(k=0;kvexnum;k++) {

for(j=0;jvexnum;j++) if(G->adj[k][j]==INFINITY) 开始 printf(\"%4s\else

printf(\"%4d\printf(\"\\n\\n\"); }

输出第k个顶点 判断k是否小于顶点总数 k=0 k=0

} YN YN Y

以邻接矩阵作为图的存储结构建立图 MGraph*create_graph()

/*以邻接矩阵作为图的存储结构建立图*/ {

charinchar[100],enchar[100],fvex,lvex; intcount=0; intweight; MGraph*G; ArcType*arc;

printf(\"首先进行图的初始化!!\\n\\n\"); G=(MGraph*)malloc(sizeof(MGraph)); G=Init_MGraph();

arc=(ArcType*)malloc(sizeof(ArcType));

printf(\"\\n请以(顶点,顶点,权值)的形式输入图的边(或弧),第一个顶点是?表示结束:\\n\"); while(1) {

scanf(\"%s\输入第一个顶点,?结束*/

if(fvex=='?')break; else {

AddVertex(G,fvex);

scanf(\"%s\scanf(\"%d\输入第二个顶点和权值*/ arc->vex1=fvex;arc->vex2=lvex; arc->ArcVal=weight;AddArc(G,arc); printf(\"\\n请继续输入下一条边(或弧)!!\\n\"); } }

return(G); }

将邻接矩阵g转换成邻接表G

ALGraph*MGraphToALGraph(MGraph*g,ALGraph*G) {

inti,j,n=g->vexnum;//n为顶点数 ArcNode*p;

G=(ALGraph*)malloc(sizeof(ALGraph)); G->arcnum=g->arcnum; G->vexnum=g->vexnum; for(i=0;ivexnum;i++)

G->AdjList[i].firstarc=NULL;

for(i=0;ifor(j=n-1;j>=0;j--)

if(g->adj[i][j]!=INFINITY)//邻接矩阵的当前元素不为 {

p=(ArcNode*)malloc(sizeof(ArcNode));//创建一个结点*p G->AdjList[j].data=g->vexs[j]; p->adjvex=g->vexs[j]; p->info=g->adj[i][j];

p->nextarc=G->AdjList[i].firstarc;//将*p链到链表后

G->AdjList[i].firstarc=p;

} } returnG; }

邻接链表的输出

voidoutput_graphic_c(MGraph*g,ALGraph*G) 把顶点总数赋值给n { inti; ArcNode*p;

把邻接矩阵的边总数赋值给邻接链表的边总数 开始 把邻接矩阵的顶点总数赋值给邻接链表的顶点总数 用循环结构把每一个顶点的头指针初始化

for(i=0;ivexnum;i++) {

printf(\"%c\p=G->AdjList[i].firstarc; while(p!=NULL) {

printf(\"%s\

printf(\"(%c,%d)\p=p->nextarc; }

printf(\"\\n\\n\"); } }

相邻景点查询并输出

voidoutput_Find_ALGraph(ALGraph*G) {/*相邻景点查询并输出*/ intj; ArcNode*p;

printf(\"请输入你要查询的景点(下标值):\\n\"); scanf(\"%d\

p=G->AdjList[j].firstarc; while(p)

{

printf(\"景点%c到景点%c的距离是%d(该两个景点之间有直接的道路相通)\\n\p=p->nextarc; }

printf(\"\\n\\n\"); }

景点路线查询:假设对于每个景点,设置有景点路线查询,要求能给出从该景点出发到任一其它景点的最短简单路径及距离。

voidDijkstra_One(ALGraph*G,MGraph*g,intv0,intdistance[],intpre[]) {//带权图G从顶点v0到其他定点的最短距离distance和最短路径前驱结点的下标pre intw;

intS[30],i,j,k,p,min;

printf(\"你所要开始查询的景点是:%c\\n\for(i=0;ivexnum;i++) {

distance[i]=g->adj[v0][i]; S[i]=0;

if(distance[i]pre[i]=-1; }

S[v0]=1;//顶点v0已加入到集合S中 for(i=0;ivexnum;i++) {

min=INFINITY;

for(j=0;jvexnum;j++) {

if(!S[j]&&distance[j]min=distance[j]; k=j; } }

S[k]=1;///将找到的顶点加入到集合S中

for(w=0;wvexnum;w++)///修改集合T中顶点的距离值 if(!S[w]&&distance[w]>distance[k]+g->adj[k][w]) {

distance[w]=distance[k]+g->adj[k][w]; pre[w]=k; } }

printf(\"查询结果:\\n\");

for(j=0;jvexnum;j++)//输出结果 if(pre[j]!=-1) {

printf(\"从景点%c到景点%c\p=pre[j];

printf(\"的最短距离是:%d\printf(\"途中经过的景点有:\"); while(p!=-1) {

printf(\"%c\p=pre[p]; }

printf(\"\\n\"); }

elseif(j!=v0)

printf(\"\\n%c到%c:nopath\} N Y

定义最短路径的终点集数组S 开始 景点路线综合查询:对于该旅游区的任意两个景点,找出它们之间的最短简单路输入要查询景点的下标值 径及距离。

用循环结构实现各数组的初始化 置S={v0}

voidDijkstra_Two(ALGraph*G,MGraph*g,intv0,intdistance[],intpre[]){ //带权图G从顶点v0到其他定点的最短距离distance和最短路径前驱结点的下标pre intw;

intS[30],i,j,k,p,min,d;

printf(\"你所要开始查询的开始景点是:%c\\n\\n\for(i=0;ivexnum;i++) {

distance[i]=g->adj[v0][i]; S[i]=0;

if(distance[i]S[v0]=1;//顶点v0已加入到集合S中 for(i=0;ivexnum;i++) {

min=INFINITY;

for(j=0;jvexnum;j++) {

if(!S[j]&&distance[j]{

min=distance[j]; k=j; } }

S[k]=1;///将找到的顶点加入到集合S中

for(w=0;wvexnum;w++)///修改集合T中顶点的距离值 if(!S[w]&&distance[w]>distance[k]+g->adj[k][w]) {

distance[w]=distance[k]+g->adj[k][w]; pre[w]=k; } }

printf(\"输入你要查询的另外一个景点(下标值):\"); scanf(\"%d\

printf(\"你要查询的另外一个景点是:%c\\n\printf(\"\\n查询结果:\\n\");//输出结果 if(pre[d]!=-1) {

printf(\"从景点%c到景点%c\p=pre[d];

printf(\"的最短距离是:%d\

printf(\"途中经过的景点有:\"); while(p!=-1) {

printf(\"%c\p=pre[p]; }

printf(\"\\n\"); } }

定义最短路径的终点集数组S 开始 最佳旅游路线确定:假设该旅游区的入口也是出口,请确定一条最佳的旅游线路,输入要查询景点的下标值 该线路必须经过所有的旅游景点(有些景点可以重复经过)且走的路最短。

用循环结构实现各数组的初始化 voiddfs_path(ALGraph*g,intsrc,intcur,intvis[],GPath*cur_path,GPath*min_path) {

if(vis[src]) {

if(cur_path->count==g->vexnum) {

if(cur_path->valuevalue) {

memcpy(min_path,cur_path,sizeof(GPath));/*由cur_path所指内存区域复制sizeof(GPath)个字节到min_path所指内存区域*/

置S={v0}

return; } } return; }

ArcNode*node=g->AdjList[cur].firstarc; for(;node!=NULL;node=node->nextarc)/*起始条node=g->AdjList[cur].firstarc*/ {

charadj=node->adjvex; intindex=LocateVex(g,adj); if(vis[index]==0) {

cur_path->vertex[cur_path->count++]=index; cur_path->value+=node->info; vis[index]=1;

dfs_path(g,src,index,vis,cur_path,min_path); cur_path->count--;

cur_path->value-=node->info; vis[index]=0;

开始 } }

用循环结构复制cur_pat的内存到min_path 把邻接表数组的头指针赋值给node 件为

} YN NY

voidbest_path(ALGraph*g,intsrc) {

intvis[MAXVEX];

memset(vis,0,sizeof(vis)); GPathcur_path,min_path;

memset(&cur_path,0,sizeof(GPath));/*将cur_path所指向的某一块内存中的每个字节的内容全部设置为0指定的ASCII值,

块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为指向cur_path的指针。*/

memset(&min_path,0,sizeof(GPath));/*将min_path所指向的某一块内存中的每个字节的内容全部设置为0指定的ASCII值,

块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为指向min_path的指针。*/ min_=INFINITY;

dfs_path(g,src,src,vis,&cur_path,&min_path); if(min_!=INFINITY) { inti=0;

printf(\"\\n最佳旅游路线景点下标值是:\\n\");

for(i=0;iprintf(\"%d->\}

printf(\"\\n\");

printf(\"\\n最佳旅游路线景点是:\\n\"); for(i=0;iprintf(\"%c->\}

printf(\"\\n\"); }else {

printf(\"建立的图中没有最佳路径\\n\"); } } 主函数 voidmain() {

intn,opse,v0,i;

intdistance[MAXVEX],pre[2*MAXVEX],path[MAXVEX]; ALGraph*G;

MGraph*M; do

{printf(\"\\n\\n请选择对图的操作要求:\\n\\n\"); for(n=0;n<=30;n++) printf(\"*\"); printf(\"\\n*\");

printf(\"1----建立图的邻接矩阵\"); printf(\"2----图的邻接矩阵的输出\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"3----图的邻接链表的输出\"); printf(\"4----相邻景点查询\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"5----从某点出发到另外所有点最短简单路径及距离\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"6----两个景点之间的最短距离(下标值)\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"7----最佳路径\"); printf(\"8----退出\");

printf(\"*\\n\"); for(n=0;n<=30;n++) printf(\"*\"); printf(\"\\n\\n\"); do

{scanf(\"%d\}while(opse<1||opse>8); switch(opse) { case1:

{M=(MGraph*)malloc(sizeof(MGraph)); M=create_graph(); printf(\"\\n\\n\"); break; } case2:

{printf(\"\\n您所建立的图是:\\n\"); output_graphic(M); break; } case3:

{printf(\"图G的邻接矩阵转换成邻接表:\\n\");

G=MGraphToALGraph(M,G); output_graphic_c(M,G); break; } case4: {

printf(\"\\n相邻景点是:\\n\"); output_Find_ALGraph(G); break; } case5: {

printf(\"\\n最短简单路径及距离是:\\n\"); scanf(\"%d\

Dijkstra_One(G,M,v0,distance,pre); break; } case6: {

printf(\"两个景点之间的最短距离(下标值):\"); scanf(\"%d\

Dijkstra_Two(G,M,v0,distance,pre);

break; } case7: {

printf(\"最佳路径(下标值):\"); Dijkstra(M,0,distance,path);

printf(\"从结点%c到其他各结点的最短距离为:\\n\for(i=1;ivexnum;i++)

printf(\"到结点%c的最短距离为%d:\\n\printf(\"从结点%c到其他各结点最短路径的前一结点为:\\n\for(i=1;ivexnum;i++) if(path[i]!=-1)

printf(\"到结点%c的前一结点为%c:\\n\break; } }

}while(opse!=8); }

开始 ……… 请选择对图的操作要求 ………

⒋ 每个题目都必须有运行时的输入数据(随机产生的数据要求输出显n=0 n<=30?

示),运行的输出结果。 建立邻接矩阵: 邻接矩阵输出: 邻接链表输出: 相邻景点查询:

从某点出发到另外所有点最短简单路径及距离: 两个景点之间的最短距离: 最佳路径:

⒌ 每个函数中应给出尽可能详细的中文注释。(源程序-全)

#include\"stdio.h\" #include\"malloc.h\" #include\"string.h\"

#defineINFINITY32767/*最大值∞*/

/*根据图的权值类型,分别定义为最大整数或实数*/ #defineMAXVEX30/*最大顶点数目*/ //邻接矩阵结构体 typedefstruct

{charvex1,vex2;/*弧或边所依附的两个顶点*/ intArcVal;/*弧或边的权值*/ }ArcType;/*弧或边的结构定义*/ typedefstruct {

intvexnum,arcnum;/*图的当前顶点数和弧数*/ charvexs[MAXVEX];/*顶点向量*/ intadj[MAXVEX][MAXVEX]; }MGraph;/*图的结构定义*/ typedefstructPath {

intvertex[MAXVEX]; intvalue; intcount; }GPath;

//邻接链表结构体 typedefstructANode {//弧的结点结构类型

intadjvex;//邻接点在头结点数组中的位置(下标) intinfo;//该弧的相关信息,这里用于存放权值 structANode*nextarc;//指向下一条弧的指针 }ArcNode;

typedefstructVnode//邻接表头结点的类型 {

chardata;//顶点信息

ArcNode*firstarc;//指向第一条弧 }VNode;

typedefstruct {

VNodeAdjList[MAXVEX];//邻接表数组 intvexnum,arcnum;//图中顶点数n和边数e }ALGraph;//图的邻接表类型 MGraph*Init_MGraph() /*图的初始化*/ {

MGraph*G;

G=(MGraph*)malloc(sizeof(MGraph));

G->vexnum=0;G->arcnum=0;/*初始化顶点数、边数*/ return(G); }

ALGraph*Init_ALGraph() /*图的初始化*/ {

ALGraph*G;

G=(ALGraph*)malloc(sizeof(ALGraph)); G->vexnum=0;

G->arcnum=0;/*初始化顶点数*/ return(G); }

intLocateVex(MGraph*G,charvp)

/*图中顶点的定位,若图中有顶点vp,返回其在顶点数组的下标值*/ { intk;

for(k=0;k<=G->vexnum;k++) if(G->vexs[k]==vp)return(k); return(-1);/*图中无此顶点*/ }

intLocateVexx(ALGraph*G,charvp)/*图的顶点定位(图的顶点定位实际上是确定一个顶点在AdjList数组中的某个元素的data域内容。)*/ { intk;

for(k=0;kvexnum;k++) if(G->AdjList[k].data==vp)

return(k);/*如果存在此顶点返回顶点数组下标值*/ return(-1);/*如果没有则返回-1(图中无此顶点)*/ }

voidAddVertex(MGraph*G,charvp) /*往图的顶点数组中增加顶点*/ { intk,j;

if(G->vexnum>=MAXVEX)

printf(\"图中顶点数已达到最多!\\n\"); else {

if(LocateVex(G,vp)==-1)//图中无此顶点 {

k=G->vexnum;G->vexs[G->vexnum++]=vp; for(j=0;jvexnum;j++) {

G->adj[j][k]=INFINITY; G->adj[k][j]=INFINITY; /*是带权的有向图或无向图*/ } } } }

voidAddArc(MGraph*G,ArcType*arc) /*往图的邻接矩阵中添加边(弧)*/ {

intk=0,j=0;

k=LocateVex(G,arc->vex1); j=LocateVex(G,arc->vex2); {

G->arcnum++;

G->adj[k][j]=arc->ArcVal; G->adj[j][k]=arc->ArcVal;

/*是无向图或带权的无向图,需对称赋值*/ } }

voidoutput_graphic(MGraph*G) /*输出图的顶点矩阵和邻接矩阵*/ { intk,j;

printf(\"图的顶点如下:\\n\"); for(k=0;kvexnum;k++) printf(\"%4c\printf(\"\\n\\n\");

printf(\"图的邻接矩阵如下:\\n\"); for(k=0;kvexnum;k++) {

for(j=0;jvexnum;j++) if(G->adj[k][j]==INFINITY) printf(\"%4s\else

printf(\"%4d\

printf(\"\\n\\n\"); } }

MGraph*create_graph()

/*以邻接矩阵作为图的存储结构建立图*/ {

charinchar[100],enchar[100],fvex,lvex; intcount=0; intweight; MGraph*G; ArcType*arc;

printf(\"首先进行图的初始化!!\\n\\n\"); G=(MGraph*)malloc(sizeof(MGraph)); G=Init_MGraph();

arc=(ArcType*)malloc(sizeof(ArcType));

printf(\"\\n请以(顶点,顶点,权值)的形式输入图的边(或弧),第一个顶点是?表示结束:\\n\"); while(1) {

scanf(\"%s\输入第一个顶点,?结束*/ if(fvex=='?')break; else

{

AddVertex(G,fvex);

scanf(\"%s\输入第二个顶点和权值*/

scanf(\"%d\

arc->vex1=fvex;arc->vex2=lvex; arc->ArcVal=weight;AddArc(G,arc); printf(\"\\n请继续输入下一条边(或弧)!!\\n\"); } }

return(G); }

//将邻接矩阵g转换成邻接表G

ALGraph*MGraphToALGraph(MGraph*g,ALGraph*G) {

inti,j,n=g->vexnum;//n为邻接矩阵顶点总数 ArcNode*p;

G=(ALGraph*)malloc(sizeof(ALGraph)); G->arcnum=g->arcnum; G->vexnum=g->vexnum; for(i=0;ivexnum;i++) G->AdjList[i].firstarc=NULL;

for(i=0;ifor(j=n-1;j>=0;j--)

if(g->adj[i][j]!=INFINITY)//邻接矩阵的当前元素不为 {

p=(ArcNode*)malloc(sizeof(ArcNode));//创建一个结点*p G->AdjList[j].data=g->vexs[j];//顶点数据元素赋值

p->adjvex=g->vexs[j];//给邻接点数组中的每一个头结点赋值 p->info=g->adj[i][j];//给邻接链表赋上权值

p->nextarc=G->AdjList[i].firstarc;//将*p链到链表后 G->AdjList[i].firstarc=p;//将i转变为邻接表数组的头结点 } } returnG; }

voidoutput_graphic_c(MGraph*g,ALGraph*G) { inti;

ArcNode*p;//ArcNode弧的结点结构类型 for(i=0;ivexnum;i++) {

printf(\"%c\输出邻接表数组的头结点元素

p=G->AdjList[i].firstarc;//邻接表的头指针 while(p!=NULL) {

printf(\"%s\整个一条单链表输出 printf(\"(%c,%d)\p=p->nextarc; }

printf(\"\\n\\n\"); } }

voidoutput_Find_ALGraph(ALGraph*G,charvp) {/*相邻景点查询并输出*/ intj; ArcNode*p;

//printf(\"请输入你要查询的景点:\\n\"); //scanf(\"%d\//scanf(\"%c\j=LocateVexx(G,vp);

p=G->AdjList[j].firstarc;//邻接表的头指针 while(p) {

printf(\"景点%c到景点%c的距离是%d(该两个景点之间有直接的道路相

通)\\n\p=p->nextarc;//指向下一个结点指针 }

printf(\"\\n\\n\"); }

voidDijkstra_One(ALGraph*G,MGraph*g,charv0,intdistance[],intpre[]) {//S[]为已求得最短路径的终点集

//带权图G从顶点v0到其他定点的最短距离distance和最短路径前驱结点的下标pre

//数组pre[n]保存从Vs到其它顶点的最短路径。若pre[i]=k,表示从Vs到Vi的最短路径中,Vi的前一个顶点是Vk, intw,m;

intS[30],i,j,k,p,min; m=LocateVexx(G,v0);

//printf(\"你所要开始查询的景点是:%c\\n\for(i=0;ivexnum;i++)/*各数组的初始化*/ {

distance[i]=g->adj[m][i]; S[i]=0;

if(distance[i]pre[i]=-1; }

S[m]=1;//顶点v0已加入到集合S中设置s={v0} for(i=0;ivexnum;i++)//找不在S中的顶点vk {

min=INFINITY;

for(j=0;jvexnum;j++) {

if(!S[j]&&distance[j]min=distance[j]; k=j;

/*求出当前最小的distance[j]值*/ } }

S[k]=1;//将找到的顶点j加入到集合S中

for(w=0;wvexnum;w++)//修改集合s中顶点的距离值 if(!S[w]&&distance[w]>distance[k]+g->adj[k][w]) {

distance[w]=distance[k]+g->adj[k][w]; pre[w]=k;//修改distance和pre数组的值 }

}

printf(\"查询结果:\\n\");//找到最短路径 for(j=0;jvexnum;j++)//输出结果 if(pre[j]!=-1) {

printf(\"从景点%c到景点%c\p=pre[j];

printf(\"的最短距离是:%d\printf(\"途中经过的景点有:\"); while(p!=-1) {

printf(\"%c\p=pre[p]; }

printf(\"\\n\"); }

elseif(j!=m)

printf(\"\\n%c到%c:nopath\}

voidDijkstra_Two(ALGraph*G,MGraph*g,charv0,chard,intdistance[],intpre[]) {

//带权图G从顶点v0到其他定点的最短距离distance和最短路径前驱结点的下标pre intw,m,n;

intS[30],i,j,k,p,min; //chard;

m=LocateVexx(G,v0);

//printf(\"你所要开始查询的开始景点是:%c\\n\\n\for(i=0;ivexnum;i++)/*各数组的初始化*/ {

distance[i]=g->adj[m][i]; S[i]=0;

if(distance[i]S[m]=1;//顶点v0已加入到集合S中设置s={v0} for(i=0;ivexnum;i++)//找不在S中的顶点vk {

min=INFINITY;

for(j=0;jvexnum;j++) {

if(!S[j]&&distance[j]min=distance[j]; k=j; }

}/*求出当前最小的distance[j]值*/ S[k]=1;//将找到的顶点加入到集合S中

for(w=0;wvexnum;w++)//修改集合s中顶点的距离值 if(!S[w]&&distance[w]>distance[k]+g->adj[k][w]) {

distance[w]=distance[k]+g->adj[k][w]; pre[w]=k;

}//修改distance和pre数组的值 }

//printf(\"输入你要查询的另外一个景点(下标值):\"); //scanf(\"%c\n=LocateVexx(G,d);

//printf(\"你要查询的另外一个景点是:%c\\n\printf(\"\\n查询结果:\\n\");//输出结果 if(pre[n]!=-1) {

printf(\"从景点%c到景点%c\

p=pre[n];

printf(\"的最短距离是:%d\printf(\"途中经过的景点有:\"); while(p!=-1) {

printf(\"%c\p=pre[p]; }

printf(\"\\n\"); } }

voiddfs_path(ALGraph*g,intsrc,intcur,intvis[],GPath*cur_path,GPath*min_path) {

if(vis[src]) {

if(cur_path->count==g->vexnum) {

if(cur_path->valuevalue) {

memcpy(min_path,cur_path,sizeof(GPath));/*由cur_path所指内存区域复制sizeof(GPath)个字节到min_path所指内存区域*/

return; } } return; }

ArcNode*node=g->AdjList[cur].firstarc; for(;node!=NULL;node=node->nextarc)/*起

node=g->AdjList[cur].firstarc*/ {

charadj=node->adjvex; intindex=LocateVexx(g,adj); if(vis[index]==0) {

cur_path->vertex[cur_path->count++]=index; cur_path->value+=node->info; vis[index]=1;

dfs_path(g,src,index,vis,cur_path,min_path); cur_path->count--;

cur_path->value-=node->info; vis[index]=0; } }

}

voidbest_path(ALGraph*g,intsrc) {

intvis[MAXVEX];

memset(vis,0,sizeof(vis)); GPathcur_path,min_path;

memset(&cur_path,0,sizeof(GPath));/*将cur_path所指向的某一块内存中的每个字节的内容全部设置为0指定的ASCII值,

块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为指向cur_path的指针。*/

memset(&min_path,0,sizeof(GPath));/*将min_path所指向的某一块内存中的每个字节的内容全部设置为0指定的ASCII值,

块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为指向min_path的指针。*/ min_=INFINITY;

dfs_path(g,src,src,vis,&cur_path,&min_path); if(min_!=INFINITY) { inti=0;

printf(\"\\n最佳旅游路线景点下标值是:\\n\"); for(i=0;iprintf(\"%d->\}

printf(\"\\n\");

printf(\"\\n最佳旅游路线景点是:\\n\"); for(i=0;iprintf(\"%c->\}

printf(\"\\n\"); }else {

printf(\"建立的图中没有最佳路径\\n\"); } }

voidmain() {intm; intn,opse; charvp,v0,d,src;

intdistance[MAXVEX],pre[2*MAXVEX]; ALGraph*G; MGraph*M; do

{printf(\"\\n\\n请选择对图的操作要求:\\n\\n\"); for(n=0;n<=5;n++) printf(\"*\"); printf(\"\\n*\");

printf(\"1----建立图的邻接矩阵\"); printf(\"2----图的邻接矩阵的输出\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"3----图的邻接链表的输出\"); printf(\"4----相邻景点查询(下标值)\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"5----从某点出发到另外所有点最短简单路径及距离(下标值)\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"6----两个景点之间的最短距离(下标值)\"); printf(\"*\\n\"); printf(\"\\n*\");

printf(\"7----最佳路径\"); printf(\"8----退出\"); printf(\"*\\n\"); for(n=0;n<=5;n++)

printf(\"*\"); printf(\"\\n\\n\"); do

{scanf(\"%d\}while(opse<1||opse>8); switch(opse) { case1:

{M=(MGraph*)malloc(sizeof(MGraph)); M=create_graph(); printf(\"\\n\\n\"); break; } case2:

{printf(\"\\n您所建立的图是:\\n\"); output_graphic(M); break; } case3:

{printf(\"图G的邻接矩阵转换成邻接表:\\n\"); G=MGraphToALGraph(M,G); output_graphic_c(M,G);

break; } case4: {

printf(\"\\n请输入你要查询的景点:\\n\"); scanf(\"%c\

output_Find_ALGraph(G,vp); break; } case5: {

printf(\"\\n输入一个顶点是:\\n\"); scanf(\"%c\

Dijkstra_One(G,M,v0,distance,pre); break; } case6: {

printf(\"你所要开始查询的开始景点是:\\n\\n\"); scanf(\"%c\

printf(\"你要查询的另外一个景点是:\\n\"); scanf(\"%c\

Dijkstra_Two(G,M,v0,d,distance,pre); break; } case7: {

printf(\"输入你要查询的开始景点:\"); scanf(\"%c\m=LocateVexx(G,v0); best_path(G,m); break; } }

}while(opse!=8); }

⒍ 问题与总结 问题:

1、第一次答辩的时候,老师要求景点名称在后面也要输入字符型,回来后,想了一下,用了一个简单的办法,即调用LocateVexx函数返回我输入景点所对应的下标值。这样就避免了只能输入下标值带来的不便了;

2、没有完全符合最后一题的意思完成该题,最后一小题题目要求是可以重复经过某些点,但是我的程序是每个点只经过一次的最短

回路(即所建的图需是哈密顿图才有回路,否则会输出没有最短路径);为了解决这个问题,我在网上也看了很多的资料,比如:TSP问题(旅行商问题/货郎担问题)、蚁群算法、、模拟退火算法、KM算法、中国邮递员算法等,其中发现经典的旅行商问题(货郎担问题)并不符合题目最后一题的要求,下面是在网上截图的资料: 为了解决这个难题,虽然在网上找了很多的资料,努力了三天,但是还是没有能力解决这个问题。

总结:将邻接矩阵转换为邻接链表走了很多弯路、花了很长的时间;还有就是引用一些书上的函数时,要正确用函数对结构体成员调用,不能照搬过来,得看一下结构上的区别。

感谢阅读

因篇幅问题不能全部显示,请点此查看更多更全内容