算法思想:
Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。
伪代码:
代码示例:
#include <iostream> #include <fstream> using namespace std; const int MAXN = 100; const int INFINITE = 100000; int Adj[MAXN][MAXN]; int N; int EXTRACT_MIN(int *d, bool *visited, int v)//从邻接点中取d最小的 { int len = INFINITE; int m = -1; for( int i = 1; i <= N; i++ ) { if( !visited[i] && d[i] < len) { len = d[i]; m = i; } } return m; } void Paint_Path(int *pre, int root) { if( pre[root] == 0 ) { printf("%d", root); } else { Paint_Path(pre, pre[root] ); printf("-->%d", root); } } void Relax(int *d, int* pre, int u, int v, int w) { if(d[v] > d[u] + w ) { d[v] = d[u] + w; pre[v] = u; } } void Dijkstra( int s ) { int i; int u; int *d; int *pre; bool *visited; d = new int[N]; pre = new int[N]; visited = new bool[N]; //initialize for( int i = 1; i <= N; i++) { d[i] = INFINITE; pre[i] = 0; } d[s] = 0; for( i = 1; i <= N; i++) { u = EXTRACT_MIN(d, visited, N); visited[u] = true; for( int j = 1; j <= N; j++) { if( !visited[j] ) { Relax(d, pre, u, j, Adj[u][j]); } } } for( i = 1; i <= N; i++) { Paint_Path(pre, i ); printf("\n"); } // delete [] d; // delete [] pre; // delete [] visited; } int main(int argc, char* argv[]) { int i, j; ifstream in("data.txt"); in >> N; for( i = 1; i <= N; i++) { for( j = 1; j <= N; j++) { in >> Adj[i][j]; } } Dijkstra(1); return 0; }
测试结果:
参考资料:
http://www.wutianqi.com/?p=1890
http://net.pku.edu.cn/~course/cs101/2007/resource/Intro2Algorithm/book6/chap25.htm