實現教科書圖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()做了修改。
這個軟件主要目的在於說明:在視窗時代,算法和數據結構並沒有過時,仍然是軟件
的靈魂。視窗手段能使界面變漂亮,但要想實現衆多的複雜功能,還必須依靠算法和數據
結構。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章