数据结构之图的基本操作-校园导游
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(" 请选择起点(0~26):"); 55 scanf("%d",&v0); 56 printf(" 请选择终点(0~26):"); 57 scanf("%d",&v1); Path(v0);//计算两个景点之间的最短路径 58 Output(v0,v1);//输出结果 59 printf(" 请按任意键继续... "); 60 getchar();//利用getchar()函数让程序运行到上一行时,等待按下下一个键才返回 61 getchar(); 62 break; 63 case'2': 64 system("cls"); 65 List();//输出景点列表 66 printf(" 请输入您要查找的景点编号:"); 67 scanf("%d",&num); 68 for(i=0;i<NUM;i++) 69 { 70 if(num==G.vex[i].number) 71 { 72 printf(" 您要查找景点信息如下:"); 73 printf(" %s:",G.vex[i].sight); 74 printf(" %s ",G.vex[i].info); 75 printf(" 按任意键返回..."); 76 getchar(); 77 getchar(); 78 break; 79 } 80 } 81 if(i==NUM) 82 { 83 printf(" 没有找到!"); 84 printf(" 按任意键返回..."); 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(" ************************************* "); 102 printf(" 1、查询景点路径 "); 103 printf(" 2、查询景点信息 "); 104 printf(" 0、退出 "); 105 printf(" ************************************* "); 106 printf(" 请输入您的选择:"); 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(" ---------------------------欢迎使用校园导游程序---------------------------- "); 224 printf(" --------------------------------------------------------------------------- "); 225 printf(" 景点名称 "); 226 printf(" --------------------------------------------------------------------------- "); 227 for(int i=0;i<NUM;i++) 228 { 229 printf(" *** (%2d)%-20s *** ",i,G.vex[i].sight);//输出景点列表 230 k=k+1; 231 } 232 printf(" ------------------------------------------------------------------------------ "); 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(" 从*%s*到*%s*的最短路径为",G.vex[sight1].sight,G.vex[sight2].sight);//输出提示信息 281 printf(" (最短距离为:%dm.) ",D[a]);//输出sight1到sight2的最短路径长度,存放在D[]数组中 282 printf(" %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(" "); 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 }