数据结构之图的基本操作-校园导游

 

1.实验题目

      分别用邻接矩阵和邻接表实现以下操作:图的创建、遍历、插入、删除、最短路径。参考题目为校园导游程序

2.需求分析

      设图的结点不超过 30 个,每个结点用一个编号表示(如果一个图有 n 个结点,则它们 的编号分别为 1,2,…,n)。通过输入图的全部边输入一个图,每个边为一个数对,可以对边 的输入顺序作出某种限制。注意,生成树的边是有向边,端点顺序不能颠倒。

3.概要设计

      1)为了实现上述程序功能,需要定义单链表的抽象数据类型:

 1   typedef struct ArcCell{
 2 
 3     int adj;
 4 
 5 }ArcCell;//定义边的类型
 6 
 7 typedef struct VertexType{
 8 
 9     int number;
10 
11     char *sight;
12 
13     char *info;
14 
15 }VertexType;//定义定点类型
16 
17  
18 
19 typedef struct MGraph{
20 
21     VertexType vex[NUM]; 
22 
23 ArcCell arc[NUM][NUM];
24 
25 int vexnum,arcnum;
26 
27 }MGraph;//定义图的类型

 

      2)本程序包含 8 个函数:

           ① 主函数main()

           ② 主菜单函数 Menu()

           ③ 图函数Create(int v,int a)

           ④ 显示景点列表函数 List()

           ⑤  计算最短路径函数 Path()

           ⑥  输出函数 Output()

           ⑦ 哈密尔顿图遍历函数 HaMiTonian() 

           ⑧ 其他函数:NextValue(int k);display().

4.详细设计

      实现概要设计中定义的所有的数据类型,对每个操作给出伪码算法。对主程序和其他模 块也都需要写出伪码算法。

   • 结点类型和指针类型

 1 typedef struct ArcCell{
 2 
 3 int adj;
 4 
 5 }ArcCell;//定义边的类型
 6 
 7 typedef struct VertexType{
 8 
 9 int number;
10 
11 char *sight;
12 
13 char *info;
14 
15 }VertexType;//定义定点类型
16 
17  
18 
19 typedef struct MGraph{
20 
21 VertexType vex[NUM]; 
22 
23 ArcCell arc[NUM][NUM];
24 
25 int vexnum,arcnum;
26 
27 }MGraph;//定义图的类型

   • 其他模块伪码算法

          主函数main()

          利用各子函数完成对景点的查询及景点间最短路径和长度的查询。

          主菜单函数 Menu()

          利用List()函数完成景点列表的输出及菜单的显示。

          图函数Create(int v,int a)

          利用结构体VertexType初始化景点及其景点描述。

          利用结构体 MGraph规定景点间的距离。

          显示景点列表函数 List()

          利用循环函数输出景点列表。

          计算最短路径函数 Path()

          利用迪杰斯特拉算法计算最短路径。

          哈密尔顿图遍历函数 HaMiTonian() 

          遍历哈密尔顿图。

5.调试分析

      用无向网表示学校的校园景点平面图,图中顶点表示主要景点,存放景点的编号,名称,简介等信息,图中的边表示景点间的道路,存放长度等信息,要求能回答有关景点介绍,游览路径等问题。游客可询问:从某一景点到另一景点的最短路径。

6.使用说明

      根据此校园导游程序,可看到所有景点名称。依据提示键入所要进行的操作:1、查询景点之间的路径  2、查询景点信息  0、退出。

      若要进行景点之间路经查询:首先键入“1”,之后根据提示,键入起点编号、终点编号,即可查询最短路径,以及最短路径的距离。

      若要进行景点信息查询:首先键入“2”,之后根据提示,键入所要查询的景点编号,即可查询景点信息。

      键入“0”即退出导游系统。

7.测试结果

       

      

 

       

 

8.附代码

  1 // 实验四.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include<stdio.h>
  6 #include<string.h>
  7 #include<malloc.h>
  8 #include<stdlib.h>
  9 #define Max 10000
 10 #define NUM 27
 11 typedef struct ArcCell{
 12     int adj;//相邻两景点的距离
 13 }ArcCell;//定义边的类型
 14 
 15 typedef struct VertexType{
 16     int number;//景点编号
 17     char *sight;//景点名称
 18     char *info;//景点描述
 19 }VertexType;//定义定点类型
 20 
 21 typedef struct MGraph{
 22     VertexType vex[NUM];  //图中顶点,即为景点
 23     ArcCell arc[NUM][NUM];//图中的边,即景点间的距离
 24     int vexnum,arcnum;//顶点数,边数
 25 }MGraph;//定义图的类型
 26 
 27 MGraph G;//定义图为全局变量
 28 int P[NUM][NUM]; 
 29 long int D[NUM];//辅助变量存储最短路径长度
 30 int x[26]={0};
 31 void Create(int v,int a);//图函数
 32 void List();//列表函数
 33 void Path(int num);//最短路径函数
 34 void Output(int sight1,int sight2);//输出函数
 35 char Menu();//主菜单
 36 void HaMiTonian(int);//哈密尔顿图的遍历
 37 void NextValue(int);
 38 void display();//显示遍历结果
 39 
 40 void main()
 41 {
 42     int v0,v1;
 43     int i,num;
 44     char flag; 
 45     Create(NUM,11);
 46     do
 47     {
 48         flag=Menu();
 49         switch(flag)
 50         {
 51         case'1':
 52             system("cls");//执行系统命令,清楚先前屏幕显示的内容
 53             List();//输出景点列表 
 54             printf("\n\n\t请选择起点(0~26):");
 55             scanf("%d",&v0);
 56             printf("\t请选择终点(0~26):");
 57             scanf("%d",&v1); Path(v0);//计算两个景点之间的最短路径
 58             Output(v0,v1);//输出结果 
 59             printf("\n\n\t请按任意键继续...\n");
 60             getchar();//利用getchar()函数让程序运行到上一行时,等待按下下一个键才返回
 61             getchar();
 62             break;
 63         case'2':
 64             system("cls");
 65             List();//输出景点列表
 66             printf("\n\n\t请输入您要查找的景点编号:");
 67             scanf("%d",&num);
 68             for(i=0;i<NUM;i++)
 69             { 
 70                 if(num==G.vex[i].number)
 71                 { 
 72                     printf("\n\n\t您要查找景点信息如下:");
 73                     printf("\n\n\t%s:",G.vex[i].sight);
 74                     printf("\t%s\n\n",G.vex[i].info);
 75                     printf("\n\t按任意键返回...");
 76                     getchar();
 77                     getchar();
 78                     break;
 79                 }
 80             }
 81             if(i==NUM)
 82             {
 83                 printf("\n\n\t没有找到!");
 84                 printf("\n\n\t按任意键返回...");
 85                 getchar();
 86                 getchar();
 87             } 
 88             break;
 89         }
 90         }while(flag!='0');
 91 } 
 92 char Menu()//主菜单
 93 {
 94     char c;
 95     int flag;
 96     do{
 97         flag=1;
 98         system("cls");
 99         List();//输出景点列表 
100 
101         printf("\t\t\t*************************************\n");
102         printf("\t\t\t           1、查询景点路径           \n");
103         printf("\t\t\t           2、查询景点信息           \n");
104         printf("\t\t\t           0、退出                   \n");
105         printf("\t\t\t*************************************\n");
106         printf("\t请输入您的选择:");
107         scanf("%c",&c);
108         if(c=='1'||c=='2'||c=='0')
109             flag=0;
110     }while(flag);
111     return c;
112 } 
113  void Create(int v,int a)//创建图函数
114  {
115      int i,j;
116      G.vexnum=v;//初始化结构中的景点数和边数 
117      G.arcnum=a; 
118      for(i=0;i<G.vexnum;++i)
119          G.vex[i].number=i;//初始化每一个景点的编号
120      //初始化没一个景点名及其景点描述
121      G.vex[0].sight="&&&大学正门";
122      G.vex[0].info="&&&大学正门正门是石家庄铁道大学最大的标志,也是&&&大学的交通关键";
123      G.vex[1].sight="第一教学楼"; 
124      G.vex[1].info="走进&&&大学正门即为一个教学楼,是学生们上课、学习的场地";
125      G.vex[2].sight="第二教学楼";
126      G.vex[2].info="位于第一教学楼西面,供学生们上课学习";
127      G.vex[3].sight="大礼堂";
128      G.vex[3].info="学校在此举行重要典礼以及各学院各社团的迎新晚会";
129      G.vex[4].sight="春晖楼";
130      G.vex[4].info="学生处和教务处的办公所在地";
131      G.vex[5].sight="图书馆"; 
132      G.vex[5].info="图书馆内设有海量图书,开拓学生视野,可供学生自习。";
133      G.vex[6].sight="留学生公寓";
134      G.vex[6].info="国外留学生生活所在地";
135      G.vex[7].sight="西操";
136      G.vex[7].info="学校在此举办运动会、升国旗仪式、大型迎新晚会";
137      G.vex[8].sight="工程训练中心";
138      G.vex[8].info="学生们进行工程训练的地方";
139      G.vex[9].sight="第三教学楼"; 
140      G.vex[9].info="位于第二教学楼北面,供学生们上课学习";
141      G.vex[10].sight="体育馆";
142      G.vex[10].info="学生们在此进行体育锻炼";
143      G.vex[11].sight="地下超市";
144      G.vex[11].info="提供各种生活学习用品,为学生提供便利";
145      G.vex[12].sight="综合服务中心";
146      G.vex[12].info="综合服务中心,为学生提供综合性服务";
147      G.vex[13].sight="土木实验楼"; 
148      G.vex[13].info="土木工程学生自习楼和土木学院老师办公楼";
149      G.vex[14].sight="信息实验楼"; 
150      G.vex[14].info="信息学院老师办公区";
151      G.vex[15].sight="第九实验楼";
152      G.vex[15].info="公共实验楼,设有机房";
153      G.vex[16].sight="校医院"; 
154      G.vex[16].info="学生医疗场所";
155      G.vex[17].sight="基础教学楼";
156      G.vex[17].info="目前学校设备最齐全的教学楼";
157      G.vex[18].sight="学生公寓";
158      G.vex[18].info="学生们休息的地方";
159      G.vex[19].sight="综合餐厅"; 
160      G.vex[19].info="学校餐厅,供学生们吃饭";
161      G.vex[20].sight="毛主席雕像";
162      G.vex[20].info="这里举行日常升国旗仪式";
163      G.vex[21].sight="第二食堂";
164      G.vex[21].info="学生吃饭的地方";
165      G.vex[22].sight="第一食堂"; 
166      G.vex[22].info="学生吃饭的地方";
167      G.vex[23].sight="大时钟";
168      G.vex[23].info="学校又一标志性建筑,每天上课的钟声从这里响起";
169      G.vex[24].sight="翠园"; 
170      G.vex[24].info="公共区域";
171      G.vex[25].sight="信园"; 
172      G.vex[25].info="内设打印店,水果摊";
173      G.vex[26].sight="&&&大学小门"; 
174      G.vex[26].info="又一学生进出学校的门口";
175       G.vex[27].sight="干休所"; 
176      G.vex[27].info="教师公寓";
177      //这里把所有的边假定为10000,含义是这两个景点之间是不可到达
178      for(i=0;i<G.vexnum;++i)
179          for(j=0;j<G.vexnum;++j)
180            G.arc[i][j].adj=Max;
181      //下边是可直接到达的景点间的距离,由于两个景点间距离是互相的,所以要对图中对称的边同时赋值
182      //上面列举并非全部景点
183      G.arc[0][1].adj=G.arc[1][0].adj=23;
184      G.arc[1][2].adj=G.arc[2][1].adj=41;
185      G.arc[1][6].adj=G.arc[6][1].adj=98;
186      G.arc[1][6].adj=G.arc[4][1].adj=70;
187      G.arc[2][8].adj=G.arc[8][2].adj=50;
188      G.arc[2][9].adj=G.arc[9][2].adj=16;
189      G.arc[2][23].adj=G.arc[23][2].adj=90;
190      G.arc[3][6].adj=G.arc[6][3].adj=112;
191      G.arc[3][17].adj=G.arc[17][3].adj=50;
192      G.arc[3][18].adj=G.arc[18][3].adj=45;
193      G.arc[3][20].adj=G.arc[20][3].adj=38;
194      G.arc[3][4].adj=G.arc[3][4].adj=80;
195      G.arc[6][16].adj=G.arc[16][6].adj=30;
196      G.arc[4][19].adj=G.arc[19][4].adj=100;
197      G.arc[4][20].adj=G.arc[20][4].adj=21;
198      G.arc[5][7].adj=G.arc[7][5].adj=62;
199      G.arc[5][8].adj=G.arc[8][5].adj=50;
200      G.arc[5][10].adj=G.arc[10][5].adj=77;
201      G.arc[5][23].adj=G.arc[23][5].adj=31;
202      G.arc[5][17].adj=G.arc[17][5].adj=100;
203      G.arc[11][15].adj=G.arc[15][11].adj=50;
204      G.arc[11][12].adj=G.arc[11][12].adj=10;
205      G.arc[11][17].adj=G.arc[17][11].adj=50;
206      G.arc[12][15].adj=G.arc[15][12].adj=44;
207      G.arc[13][12].adj=G.arc[12][13].adj=60;
208      G.arc[14][15].adj=G.arc[15][14].adj=33;
209      G.arc[15][13].adj=G.arc[13][15].adj=54;
210      G.arc[18][19].adj=G.arc[19][18].adj=30;
211      G.arc[18][20].adj=G.arc[20][18].adj=30;
212      G.arc[18][21].adj=G.arc[21][18].adj=72;
213      G.arc[18][22].adj=G.arc[22][18].adj=40;
214      G.arc[23][24].adj=G.arc[24][23].adj=30;
215      G.arc[17][25].adj=G.arc[25][17].adj=80;
216      G.arc[12][25].adj=G.arc[25][12].adj=50;
217      G.arc[27][22].adj=G.arc[22][27].adj=430;
218      G.arc[26][27].adj=G.arc[27][26].adj=200;
219     }
220 void List()//景点列表函数
221 { 
222     int k=0;
223     printf("\n\t\t---------------------------欢迎使用校园导游程序----------------------------\n");
224     printf("\n\t\t---------------------------------------------------------------------------\n");
225     printf("\t\t\t\t         景点名称       \t\t\t"); 
226     printf("\n\t\t---------------------------------------------------------------------------\n");
227     for(int i=0;i<NUM;i++)
228     {
229         printf("\t\t***\t\t(%2d)%-20s\t\t\t\t***\n",i,G.vex[i].sight);//输出景点列表
230         k=k+1;
231     } 
232     printf("\t\t------------------------------------------------------------------------------\n");
233 }
234 void Path(int num)//迪杰斯特拉算法最短路径函数num为入口点的编号
235 { 
236     int v,w,i,t;//i、w和v为计数变量
237     int final[NUM];
238     int min;
239     for(int v=0;v<NUM;v++)
240     { 
241         final[v]=0;//假设从顶点num到顶点v没有最短路径
242         D[v]=G.arc[num][v].adj;//将与之相关的权值放入D中存放
243         for(w=0;w<NUM;w++)//设置为空路径
244             P[v][w]=0; if(D[v]<20000)//存在路径
245         { 
246             P[v][num]=1;//存在标志置为一
247             P[v][v]=1;//自身到自身
248         }
249     }
250     D[num]=0;
251     final[num]=1;//初始化num顶点属于S集合
252     //开始主循环,每一次求得num到某个顶点的最短路径,并将其加入到S集合 
253     for(i=0;i<NUM;++i)//其余G.vexnum-1个顶点
254     {
255         min=Max;//当前所知离顶点num的最近距离
256         for(w=0;w<NUM;++w)
257             if(!final[w])//w顶点在v-s中
258                 if(D[w]<min)//w顶点离num顶点更近
259                 {
260                     v=w;
261                     min=D[w];
262                 }
263                 final[v]=1;//离num顶点更近的v加入到s集合
264                 for(int w=0;w<NUM;++w)//更新当前最短路径极其距离 
265                     if(!final[w]&&((min+G.arc[v][w].adj)<D[w]))
266                     {
267                         D[w]=min+G.arc[v][w].adj;
268                         for(int t=0;t<NUM;t++)
269                             P[w][t]=P[v][t];
270                             P[w][w]=1;
271                     }
272     }
273 }
274 void Output(int sight1,int sight2)//输出函数
275 {
276     int a,b,c,d,q=0;
277     a=sight2;//将景点二赋值给a
278     if(a!=sight1)//如果景点二不和景点一输入重合,则进行...
279     {
280         printf("\n\t从*%s*到*%s*的最短路径为",G.vex[sight1].sight,G.vex[sight2].sight);//输出提示信息
281         printf("\t(最短距离为:%dm.)\n\n\t",D[a]);//输出sight1到sight2的最短路径长度,存放在D[]数组中
282         printf("\t%s",G.vex[sight1].sight);//输出景点一的名称
283         d=sight1;
284         //将景点一的编号赋值给d
285         for(c=0;c<NUM;++c)
286         {
287 gate:;//标号,可以作为goto语句跳转的位置
288             P[a][sight1]=0;
289             for(b=0;b<NUM;b++)
290             {
291                 if(G.arc[d][b].adj<20000&&P[a][b])
292                 {
293                     printf("-->%s",G.vex[b].sight);//输出此节点的名称
294                     q=q+1;//计数变量加一,满8控制输出时的换行
295                     P[a][b]=0;
296                     d=b;
297                     if(q%9==0)printf("\n");
298                     goto gate;
299                 }//if(G.arcs[d][b].adj<20000&&P[a][b])
300             }    //for(b=0;b<NUM;b++)
301         }//for(c=0;c<NUM;++c)
302     }
303 }
304 
305 void HaMiTonian(int m)//哈密尔顿图的遍历
306 { 
307     if(m>26)
308         return; 
309 L:NextValue(m);//标号,可以作为goto语句跳转的位置 
310     if(x[m]==0) 
311         return;
312     if(m==26&&G.arc[0][x[26]-1].adj!=0000)
313         display();
314     else 
315         HaMiTonian(m+1);
316     goto L;//使用goto语句改变程序流向,转去执行语句标号L所标识的语句
317 
318 }
319 void NextValue(int k)
320 {
321     int j;
322 l:x[k]=(x[k]+1)%10;//标号,可以作为goto语句跳转的位置
323     if(x[k]==0)
324         return;
325     if(G.arc[x[k-1]-1][x[k]-1].adj!=10000)
326     {
327         for(j=0;j<k;j++)
328             if(x[j]==x[k])
329                 goto l;
330                 return;
331     }
332     else
333         goto l;//使用goto语句改变程序流向,转去执行语句标号l所标识的语句
334 }
335 
336 void display()
337 {
338     int i=0;
339     for(i=0;i<26;i++)
340         printf("%s->",G.vex[x[i]-1].sight);
341 }
View Code

 

 posted on 2021-01-13 17:29  ぺあ紫泪°冰封ヤ  阅读(717)  评论(0编辑  收藏  举报
Live2D