從某個源點到指定地點的最短路徑(迪傑斯特拉算法的實現)

// algo7-6.cpp 實現算法7.15的程序。迪傑斯特拉算法的實現
#include"c1.h"
#define MAX_NAME 5 // 頂點字符串的最大長度+1
#define MAX_INFO 20 // 相關信息字符串的最大長度+1
typedef int VRType;
typedef char InfoType;
typedef char VertexType[MAX_NAME];
#include"c7-1.h" // 鄰接矩陣存儲結構
#include"bo7-1.cpp" // 鄰接矩陣存儲結構的基本操作
typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 路徑矩陣,二維數組
typedef int ShortPathTable[MAX_VERTEX_NUM]; // 最短距離表,一維數組
void ShortestPath_DIJ(MGraph G,int v0,PathMatrix P,ShortPathTable D)
{ // 用Dijkstra算法求有向網G的v0頂點到其餘頂點v的最短路徑P[v]及帶權長度
	// D[v]。若P[v][w]爲TRUE,則w是從v0到v當前求得最短路徑上的頂點。
	// final[v]爲TRUE當且僅當v∈S,即已經求得從v0到v的最短路徑算法7.15
	int v,w,i,j,min;
	Status final[MAX_VERTEX_NUM]; // 輔助矩陣,爲真表示該頂點到v0的最短距離已求出,初值爲假
	for(v=0;v<G.vexnum;++v)
	{
		final[v]=FALSE; // 設初值
		D[v]=G.arcs[v0][v].adj; // D[]存放v0到v的最短距離,初值爲v0到v的直接距離
		for(w=0;w<G.vexnum;++w)
			P[v][w]=FALSE; // 設P[][]初值爲FALSE,沒有路徑
		if(D[v]<INFINITY) // v0到v有直接路徑
			P[v][v0]=P[v][v]=TRUE; // 一維數組p[v][]表示源點v0到v最短路徑通過的頂點
	}
	D[v0]=0; // v0到v0距離爲0
	final[v0]=TRUE; // v0頂點併入S集
	for(i=1;i<G.vexnum;++i) // 其餘G.vexnum-1個頂點
	{ // 開始主循環,每次求得v0到某個頂點v的最短路徑,並將v併入S集
		min=INFINITY; // 當前所知離v0頂點的最近距離,設初值爲∞
		for(w=0;w<G.vexnum;++w) // 對所有頂點檢查
			if(!final[w]&&D[w]<min) //在S集之外的頂點中找離v0最近的頂點,並將其賦給v,距離賦給min
			{
				v=w;
				min=D[w];
			}
			final[v]=TRUE; // 將v併入S集
			for(w=0;w<G.vexnum;++w) // 根據新併入的頂點,更新不在S集的頂點到v0的距離和路徑數組
				if(!final[w]&&min<INFINITY&&G.arcs[v][w].adj<INFINITY&&(min+G.arcs[v][w].adj<D[w]))
				{ // w不屬於S集且v0→v→w的距離<目前v0→w的距離
					D[w]=min+G.arcs[v][w].adj; // 更新D[w]
					for(j=0;j<G.vexnum;++j) // 修改P[w],v0到w經過的頂點包括v0到v經過的頂點再加上頂點w
						P[w][j]=P[v][j];
					P[w][w]=TRUE;
				}
	}
}
void main()
{
	int i,j;
	MGraph g;
	PathMatrix p; // 二維數組,路徑矩陣
	ShortPathTable d; // 一維數組,最短距離表
	CreateDN(g); // 構造有向網g
	Display(g); // 輸出有向網g
	ShortestPath_DIJ(g,0,p,d);//以g中位置爲0的頂點爲源點,球其到其餘各頂點的最短距離。存於d中
	printf("最短路徑數組p[i][j]如下:\n");
	for(i=0;i<g.vexnum;++i)
	{
		for(j=0;j<g.vexnum;++j)
			printf("%2d",p[i][j]);
		printf("\n");
	}
	printf("%s到各頂點的最短路徑長度爲\n",g.vexs[0]);
	for(i=0;i<g.vexnum;++i)
		if(i!=0)
			printf("%s-%s:%d\n",g.vexs[0],g.vexs[i],d[i]);
}

代碼的運行結果:

請輸入有向網G的頂點數,弧數,弧是否含其它信息(是:1,否:0): 6,8,0(見圖768)
請輸入6個頂點的值(<5個字符):
V0 V1 V2 V3 V4 V5
請輸入8條弧的弧尾弧頭權值(以空格作爲間隔):
V0 V5 100
V0 V4 30
V0 V2 10
V1 V2 5
V2 V3 50
V3 V5 10
V4 V3 20
V4 V5 60
6個頂點8條邊或弧的有向網。頂點依次是: V0 V1 V2 V3 V4 V5
G.arcs.adj:
32767 32767 10 32767 30 100
32767 32767 5 32767 32767 32767
32767 32767 32767 50 32767 32767
32767 32767 32767 32767 32767 10
32767 32767 32767 20 32767 60
32767 32767 32767 32767 32767 32767
G.arcs.info:
頂點1(弧尾) 頂點2(弧頭) 該邊或弧的信息:
最短路徑數組p[i][j]如下:
0 0 0 0 0 0
0 0 0 0 0 0
1 0 1 0 0 0
1 0 0 1 1 0
1 0 0 0 1 0
1 0 0 1 1 1

V0到各頂點的最短路徑長度爲
V0-V1:32767
V0-V2:10
V0-V3:50
V0-V4:30
V0-V5:60


函數ShortestPath_DIJ()利用2 個輔助數組final[]和D[]求得給定點v0 到圖G 中其餘
各頂點的最短距離。D[]存放當前v0 到其餘各頂點的最短距離,final[]的初值爲FALSE。
final[]的值爲TRUE,表示v0 到該頂點的最短距離已求出。圖769 通過final[]和D[]的
變化演示了求解過程。

首先,final[]的初值中只有final[v0]爲真,最短距離頂點集S 中只有頂點v0(源點,
此例中實參爲V0)。D[]的初值是鄰接矩陣中v0 行所對應的值。另令D[v0]=0(v0 到自己
的距離當然爲0)。v0 到某頂點i 的最短距離可能是二者的直接距離G.arcs[v0][i].adj,也
可能是由v0 出發,經過其它頂點,最後到達頂點i 的距離。如圖768 中V0 到V5 的最
短距離不是它們的直接距離100,而是由V0 經過V4、V3,最後到達V5 的距離60。
根據圖769(a),在不屬於S 集的頂點中,V0 到V2 的距離最短。可以斷定,V0 到
V2 的距離10 是最短距離。V0 通過其它頂點繞道到達V2 的距離一定會比10 大,故將V2
併入S 集中(final[2]=TRUE)。並考察S 集外的頂點中,有沒有哪個頂點i,使得V0 先到
V2(距離爲10),再由V2 到達頂點i 比直接從V0 到達頂點i 的距離要小?也就是滿足
10+G.arcs[2][i].adj<D[i]。如有,則改寫D[i]。V0 本無直接到達V3 的路徑,但有V0
→V2→V3 的路徑,爲10+G.arcs[2][3].adj=10+50=60,故改寫D[3]=60,如圖769(b)
所示。用這樣的方法,依次將V4、V3 和 V5 併入S。詳見圖769(c)、(d)和(e)。
通過final[]和D[]可求得給定點v0 到圖G 中其餘各頂點的最短距離是多少。但卻不
知道其間通過哪些頂點。矩陣P[][]有這些頂點的信息。以程序運行結果爲例,1 維數組
p[2][]中的1 是V0 到V2 經過的頂點(只有V0 和V2 兩個頂點);p[3][]中的1 是V0 到
V3 經過的頂點(V0、V3 和V4)。

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