void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D)
{
/**
* 核心原理:
* 記已求得的最短路徑終點的集合爲S,假設要加入的終點是x頂點,那麼下一條最短路徑要麼是
* 直接弧(v0,x),要麼就是中間經過S中頂點而最後到達終點x的路徑(v0,...,x)。
* 證明:(反證法)
* 假設下一條最短路徑中經過一個頂點不在S中,那麼說明存在一條終點不在S而長度比此路徑短的路徑。
* 但是這是不可能的,因爲算法是按路徑長度遞增的次序來產生各路徑的,故長度比此路徑短的所有路徑
* 均已產生,它們的終點必定在S中,即假設不成立。(理解:如果有一條最短路徑中經過一個頂點不在
* S中,由於這個不在S中的頂點到終點x的弧權值大於0,所以從起始點v0到這個頂點的最短路徑比起始
* 點v0到終點x的最短路徑肯定要短,那麼這一次選取的終點就不應該是x了,與假設矛盾。)
*/
/**
* 定義說明:
* 用Dijkstra算法求v0點到其它各個頂點的最短路徑問題。
* G表示用二維表數組表示的圖信息,其中(v,w)表示頂點v到頂點w的邊權值。
* v0表示圖G中的起始點。
* D是一個記錄起始點v0到各個頂點的最短路徑長度的一維數組。
* 若P[v][w]爲TRUE,則表示從v0頂點到v頂點的最短路徑經過w頂點。
* 若final[v]爲TRUE,則表示v頂點已經被包含在最短路徑集合中。
*/
/**
* 處理過程:
* 1. 初始化操作(最短路徑頂點集合S、最短路徑矩陣P、最短路徑數組D)
* 2. 主循環操作
* 2.1 根據最短路徑數組D來挑選一個頂點加入到已處理的集合S中(最短路徑頂點集合S)
* 2.2 最新當前最短路徑數組D和最短路徑矩陣P(最短路徑矩陣P、最短路徑數組D)
*/
int v = 0;
int w = 0;
int i = 0;
int j = 0;
int min = INF; /** INF表示無窮大 */
int* final = new int[G.vexnum]; /** 表示最短路徑頂點集合S */
/** 初始化操作(最短路徑頂點集合S、最短路徑矩陣P、最短路徑數組D) */
for(v = 0; v < G.vexnum; v++)
{
final[v] = FALSE; /** 初始化最短路徑頂點集合S */
D[v] = G.arcs[0][v]; /** 初始化最短路徑數組D */
for(w = 0; w < G.vexnum; w++)
{
P[v][w] = FALSE; /** 初始化最短路徑矩陣P */
}
if(D[v] < INF)
{
/** 第一次以起始點v0來記錄最短路徑矩陣P */
P[v][v0] = TRUE;
P[v][v] = TRUE;
}
}
final[v0] = TRUE; /** 第一次以起始點v0加入到最短路徑頂點集合S */
D[0] = 0; /** 第一次以起始點v0記錄初始化最短路徑數組D */
/** 主循環操作 */
for(i = 1; i < G.vexnum; i++)
{
/** 根據最短路徑數組D來挑選一個頂點加入到已處理的集合S中 */
min = INF;
for(w = 0; w < G.vexnum; w++)
{
if(!final[w] && min > D[w])
{
min = D[w];
v = w;
}
}
final[v] = TRUE; /** 更新最短路徑頂點集合S(將新頂點加入集合S中) */
for(w = 0; w < G.vexnum; w++)
{
if(!final[w] && min + G.arcs[v][w] < D[w])
{
D[w] = min + G.arcs[v][w]; /** 更新最短路徑數組D(保持D數組是最小的路徑值) */
/** 更新最短路徑矩陣P(記錄到P[w][w]最短路徑經過自身,且照搬前面頂點v的路徑過程) */
P[w][w] = TRUE;
for(j = 0; j < G.vexnum; j++)
{
P[w][j] = P[v][j];
}
}
}
}
}
輕鬆掌握Dijkstra算法(最短路徑算法)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.