实现教科书图7.33的程序(另加孤立顶点台北)(两城市之间的最短路径模拟)

// algo7-9.cpp 实现教科书图7.33的程序(另加孤立顶点台北)
#define MAX_NAME 9 // 顶点字符串的最大长度+1
#define MAX_INFO 20 // 相关信息字符串的最大长度+1
typedef int VRType;
typedef char VertexType[MAX_NAME];
typedef char InfoType;
#include"c1.h"
#include"c7-1.h" // 邻接矩阵存储结构
#include"bo7-1.cpp" // 邻接矩阵存储结构的基本操作
typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 3维数组
typedef int DistancMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 2维数组
#include"func7-2.cpp" // 求有向网中各对顶点之间最短距离的Floyd算法
void path(MGraph G,PathMatrix P,int i,int j)
{ // 求由序号为i的起点城市到序号为j的终点城市最短路径沿途所经过的城市
	int k;
	int m=i; // 起点城市序号赋给m
	printf("依次经过的城市:\n");
	while(m!=j) // 没到终点城市
	{
		G.arcs[m][m].adj=INFINITY; // 对角元素赋值无穷大
		for(k=0;k<G.vexnum;k++)
			if(G.arcs[m][k].adj<INFINITY&&P[m][j][k]) // m到k有直接通路,且k在m到j的最短路径上
			{
				printf("%s ",G.vexs[m]);
				G.arcs[m][k].adj=G.arcs[k][m].adj=INFINITY; // 将直接通路设为不通
				m=k; // 经过的城市序号赋给m,继续查找
				break;
			}
	}
	printf("%s\n",G.vexs[j]); // 输出终点城市
}
void main()
{
	MGraph g;
	int i,j,k,q=1;
	PathMatrix p; // 3维数组
	DistancMatrix d; // 2维数组
	printf("数据文件名为map.txt\n");
	CreateFUDN(g); // 通过文件构造无向网g
	for(i=0;i<g.vexnum;i++)
		g.arcs[i][i].adj=0; // ShortestPath_FLOYD()要求对角元素值为0,因为两点相同,其距离为0
	ShortestPath_FLOYD(g,p,d); // 求每对顶点间的最短路径,在func7-2.cpp中
	while(q)
	{
		printf("请选择:1 查询0 结束\n");
		scanf("%d",&q);
		if(q)
		{
			for(i=0;i<g.vexnum;i++)
			{
				printf("%2d %-9s",i+1,g.vexs[i]);
				if(i%6==5) // 输出6个数据就换行
					printf("\n");
			}
			printf("\n请输入要查询的起点城市代码终点城市代码: ");
			scanf("%d%d",&i,&j);
			if(d[i-1][j-1]<INFINITY) // 有通路
			{
				printf("%s到%s的最短距离为%d\n",g.vexs[i-1],g.vexs[j-1],d[i-1][j-1]);
				path(g,p,i-1,j-1); // 求最短路径上由起点城市到终点城市沿途所经过的城市
			}
			else
				printf("%s到%s没有路径可通\n",g.vexs[i-1],g.vexs[j-1]);
			printf("与%s到%s有关的p矩阵:\n",g.vexs[i-1],g.vexs[j-1]);
			for(k=0;k<g.vexnum;k++)
				printf("%2d",p[i-1][j-1][k]);
			printf("\n");
		}
	}
}

代码的运行结果:

数据文件名为map.txt
请输入数据文件名:map.txt
请选择:1 查询0 结束
1
1 乌鲁木齐2 呼和浩特3 哈尔滨4 西宁5 兰州6 成都
7 昆明8 贵阳9 南宁10 柳州11 株州12 广州
13 深圳14 南昌15 福州16 上海17 武汉18 西安
19 郑州20 徐州21 北京22 天津23 沈阳24 大连
25 长春26 台北
请输入要查询的起点城市代码终点城市代码: 1 10
乌鲁木齐到柳州的最短距离为4694
依次经过的城市:
乌鲁木齐兰州西安郑州武汉株州柳州
与乌鲁木齐到柳州有关的p矩阵:
1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0
请选择:1 查询0 结束
1
1 乌鲁木齐2 呼和浩特3 哈尔滨4 西宁5 兰州6 成都
7 昆明8 贵阳9 南宁10 柳州11 株州12 广州
13 深圳14 南昌15 福州16 上海17 武汉18 西安
19 郑州20 徐州21 北京22 天津23 沈阳24 大连
25 长春26 台北
请输入要查询的起点城市代码终点城市代码: 21 26
北京到台北没有路径可通
与北京到台北有关的p矩阵:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
请选择:1 查询0 结束
0

和algo7-6.cpp 中的ShortestPath_DIJ()类似,algo7-9.cpp 中的ShortestPath_FLOYD()
也有存放最短路径通过的顶点的数组P。在这里,数组P 是三维的。一维数组P[v][w][]
中的信息是从顶点v 到顶点w 最短距离所通过的顶点。如P[v][w][u]=1,说明从顶点v
到顶点w 最短距离通过顶点u。而P[v][w][t]=0,说明从顶点v 到顶点w 最短距离不通
过顶点t。以上面的程序运行结果为例,D[0][9]是乌鲁木齐到柳州的最短距离,
P[0][9][]={ 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0},对照序号可知,乌鲁木齐到
柳州的最短距离经过乌鲁木齐、兰州、柳州、株州、武汉、西安和郑州7 个城市。
为了求得依次经过的城市,调用path()。path()的算法是:对于从顶点v 到顶点w 最
短距离路径的起点v,它的下一点u 是满足G.arcs[v][u].adj 不是无穷(v 到u 有直接通路)
同时P[v][w][u]=1(u 在v 到w 的最短路径上)条件的惟一顶点。将G.arcs[v][u].adj 改
为无穷(避免又回头找v),再从u 找满足G.arcs[u][x].adj 不是无穷(u 到x 有直接通路)
同时P[v][w][x]=1(x 在v 到w 的最短路径上)条件的惟一顶点x。循环这个过程,直至到
达终点w。以上程序运行结果验证了path()的作用。

孤立顶点台北和北京不在同一个连通分量中,故它们之间没有路径可通。对应的一维
数组P[20][25][]是全0。
algo7-9.cpp 虽然能够求得任意两城市间的最短路径,但它的DOS 界面总让我们感到
不方便。我们也可以在可视化的界面下实现algo7-9.cpp 的功能。
光盘VC\shortest 子目录中的软件实现了algo7-9.cpp 的可视化。在Visual C++6.0 环
境下打开文件VC\shortest\shortest.dsw,按F7 编译后,按Ctrl+F5 运行,就会出现图
771 所示界面。


移动鼠标光标到待查询的起点城市圆圈中并单击鼠标左键,即选定了起点城市。该城
市的圆圈变成虚线。再移动鼠标光标到待查询的终点城市圆圈中并再次单击鼠标左键,即
选定了终点城市。这时,从起点城市到终点城市最短距离的沿途城市圆圈及沿线均变成虚
线,显示出求得的最短路径。同时,在图的右部中间还用文字说明两城市间的最短距离及
依次经过的城市。
图772 是运行VC\shortest 子目录中的程序并依次用鼠标左键单击南昌和天津的结
果。这个过程可以反复进行,直到按下“退出”按钮。
如果没有Visual C++6.0 软件,可将文件VC\shortest\Debug\shortest.exe 和文件
VC\shortest\mapvc.txt 拷到硬盘的同一个子目录下,直接运行shortest.exe 即可。
algo7-9.cpp 的许多函数都嵌到VC\shortest 软件中了。有一些根据具体情况做了修
改。如mapvc.txt 的内容如下:


26
30
乌鲁木齐31 26
呼和浩特277 86
哈尔滨607 26
西宁109 142
兰州175 154
成都169 214
昆明103 282
贵阳187 274
南宁187 318
柳州247 298
株州307 262
广州295 322
深圳355 334
南昌379 262
福州445 274
上海463 218
武汉349 222
西安253 170
郑州337 170
徐州415 170
北京385 98
天津445 114
沈阳523 90
大连493 150
长春565 58

台北475 318
乌鲁木齐兰州1892
呼和浩特兰州1145
⋯⋯(以下同数据文件map.txt,故略)

和algo7-9.cpp 调用的数据文件map.txt 相比,mapvc.txt 中的顶点信息不仅有城市名
称,还有城市在图中的x、y 坐标。因此,顶点信息用结构体bb 来表示:
struct bb
{
VertexType a;
int x;
int y;
};
其中,VertexType 仍然是字符串类型,存放城市名称。同时,由文件构造无向网的函
数CreateFUDN() 也做了相应的修改。求有向网中各对顶点之间最短路径的函数
ShortestPath_FLOYD()直接用在了程序中。求由起点城市到终点城市最短路径沿途所经过
城市的函数path()做了修改。
这个软件主要目的在于说明:在视窗时代,算法和数据结构并没有过时,仍然是软件
的灵魂。视窗手段能使界面变漂亮,但要想实现众多的复杂功能,还必须依靠算法和数据
结构。

posted @ 2014-09-14 09:12  meiyouor  阅读(295)  评论(0编辑  收藏  举报