原理解析
http://blog.csdn.net/wizard_wsq/article/details/51095853
小技巧總結
圖用鄰接矩陣表示
Distance[i]表示v0到頂點i的距離
int prev[i]表示節點v0到節點i存在最短路徑時,其前一個節點。
Dijkstra代碼
//Dijkstra算法函數,求給定頂點到其餘各點的最短路徑
//參數:鄰接矩陣、出發點的下標、結果數組、路徑前一點記錄
//Graph[][N],表示加權有向圖的鄰接矩陣,其中Graph[i][j]=M=65536,表示i到j不可直接到達
//v0表示以v0頂點開始尋找到其他頂點的距離
//Distance[i]表示v0到頂點i的距離
//prev[]表示
void Dijkstra(int Graph[][N], int v0, int Distance[], int prev[])
{
bool visited[N];//表示是否已經訪問過
int i, j, u;
//初始化
for (int i = 0; i<N; i++)
{
Distance[i] = Graph[v0][i];//包含了Distance[v0] = 0;
visited[i] = 0;
if (Distance[i] == M)
prev[i] = -1;
else
prev[i] = v0;
}
visited[v0] = 1;
for (i = 1; i < N; i++)//每循環一次,求得一個最短路徑
{
int mindis=M, dis;//在當前還未找到最短路徑的頂點中,尋找具有最短距離的頂點
u = v0;
for (j = 0; j < N; j++) //求離出發點最近的頂點
if (visited[j] == 0 && Distance[j]<mindis)
{
mindis = Distance[j];
u = j;
}
visited[u] = 1;
for (j = 0; j<N; j++) //由於新增了頂點u,所以要更新每個未被訪問的頂點的distance。只會由u來影響
if (visited[j] == 0 && Graph[u][j]<M)
{ //對還未求得最短路徑的頂點。求出由最近的頂點 直達各頂點的距離
dis = Distance[u] + Graph[u][j];
// 如果新的路徑更短,就替換掉原路徑
if (Distance[j] > dis)
{
Distance[j] = dis;
prev[j] = u;
}
} // if 語句體結束,j循環結束
} // i循環結束
}
Test代碼
#pragma once
#include<iostream>
#include <cstdio>
#include <list>
#include <vector>
#include <queue>
#include<stack>
#include<fstream>
#define M 65535 //無窮大
#define N 5 //頂點數
//Dijkstra算法函數,求給定頂點到其餘各點的最短路徑
//參數:鄰接矩陣、出發點的下標、結果數組、路徑前一點記錄
//Graph[][N],表示加權有向圖的鄰接矩陣,其中Graph[i][j]=M=65536,表示i到j不可直接到達
//v0表示以v0頂點開始尋找到其他頂點的距離
//Distance[i]表示v0到頂點i的距離
//prev[]表示
void Dijkstra(int Graph[][N], int v0, int Distance[], int prev[])
{
bool visited[N];//表示是否已經訪問過
int i, j, u;
//初始化
for (int i = 0; i<N; i++)
{
Distance[i] = Graph[v0][i];//包含了Distance[v0] = 0;
visited[i] = 0;
if (Distance[i] == M)
prev[i] = -1;
else
prev[i] = v0;
}
visited[v0] = 1;
for (i = 1; i < N; i++)//每循環一次,求得一個最短路徑
{
int mindis=M, dis;//在當前還未找到最短路徑的頂點中,尋找具有最短距離的頂點
u = v0;
for (j = 0; j < N; j++) //求離出發點最近的頂點
if (visited[j] == 0 && Distance[j]<mindis)
{
mindis = Distance[j];
u = j;
}
visited[u] = 1;
for (j = 0; j<N; j++) //由於新增了頂點u,所以要更新每個未被訪問的頂點的distance。只會由u來影響
if (visited[j] == 0 && Graph[u][j]<M)
{ //對還未求得最短路徑的頂點。求出由最近的頂點 直達各頂點的距離
dis = Distance[u] + Graph[u][j];
// 如果新的路徑更短,就替換掉原路徑
if (Distance[j] > dis)
{
Distance[j] = dis;
prev[j] = u;
}
} // if 語句體結束,j循環結束
} // i循環結束
}
// 參數:路徑前一點記錄、出發點的下標、到達點下標
void PrintPrev(int prev[], int v0, int vn)
{
int tmp = vn;
int i, j;
//臨時存路徑
int tmpprv[N];
//初始化數組
for (i = 0; i < N; i++)
tmpprv[i] = 0;
//記錄到達點下標
tmpprv[0] = vn + 1;
//中間點用循環記錄
for (i = 0, j = 1; j < N; j++)
{
if (prev[tmp] != -1 && tmp != 0)
{
tmpprv[i] = prev[tmp] + 1;
tmp = prev[tmp];
i++;
}
else break;
}
//輸出路徑,數組逆向輸出
for (i = N - 1; i >= 0; i--)
{
if (tmpprv[i] != 0)
{ //排除0元素
printf("V%d", tmpprv[i]);
if (i) //不是最後一個輸出符號
printf("-->");
}
}
printf("-->V%d", vn + 1);
}
//主函數
void test_dijkstra()
{
//給出有向網的頂點數組
char *Vertex[N] = { "V1", "V2", "V3", "V4", "V5" };
//給出有向網的鄰接矩陣
int Graph[N][N] = {
{ 0, 10, M, 30, 100 },
{ M, 0, 50, M, M },
{ M, M, 0, M, 10 },
{ M, M, 20, 0, 60 },
{ M, M, M, M, 0 },
};
int Distance[N]; //存放求得的最短路徑長度
int prev[N]; //存放求得的最短路徑
int i;
//調用Dijkstra算法函數,求頂點V1到其餘各點的最短路徑
//參數:鄰接矩陣、出發點的下標、結果數組、路徑前一點記錄
Dijkstra(Graph, 0, Distance, prev);
for (i = 0; i < N; i++)
{
//輸出最短路徑長度
cout << Vertex[0] << " " << Vertex[i] << " " << Distance[i]<<" ";
//printf("%visited-->%visited:%d\t", Vertex[0], Vertex[i], Distance[i]);
//輸出最短路徑
PrintPrev(prev, 0, i);
printf("\n");
}
}