Dijkstra 算法介绍以及实现

来源:互联网 发布:java怎么写入csv文件 编辑:程序博客网 时间:2024/05/18 16:17

Dijkstra算法的具体实现方法为:


1. 设置两个顶点的集合T和S:
a) S中存放已找到最短路径的顶点,初始时,集合S中只有一个顶点,即源点v0;
b) T中存放当前还未找到最短路径的顶点;

2.在T集合中选取当前长度最短的一条最短路径(v0,…,vk),从而将vk加入到顶点集合S中,并修改源点v0到T中各顶点的最短路径长度;重复这一步骤,直到所有的顶点都加入到集合S中,算法就结束了。


算法实现:
在Dijkstra算法里,为了求源点v0到其他各顶点vi的最短路径及其长度,需要设置3个数组:
a) dist[n]:dist[i]表示当前找到的从源点v0到终点vi的最短路径的长度,初始时,dist[i]为Edge[v0][i],即邻接矩阵的第v0行。
b) S[n]:S[i]为0表示顶点vi还未加入到集合S中,S[i]为1表示vi已经加入到集合S中。初始时,S[v0]为1,其余为0,表示最初集合S中只有顶点v0。
c) path[n]:path[i]表示v0到vi的最短路径上顶点vi的前一个顶点序号。采用“倒向追踪”的方法,可以确定v0到顶点vi的最短路径上的每个顶点。


在Dijkstra算法里,重复做以下3步工作:

1)  在数组dist[n]里查找S[i] != 1,并且dist[i]最小的顶点u;
2)  将S[u]改为1,表示顶点u已经加入进来了;
3)  修改T集合中每个顶点vk的dist及path数组元素值:当S[k] != 1,且顶点u到顶点vk有边(Edge[u][k]<MAX),且dist[u] + Edge[u][k] < dist[k],则修改dist[k]为dist[u] + Edge[u][k],修改path[k]为u。

因此Dijkstra算法的递推公式(求源点v0到各顶点的最短路径)为:


eg:

      利用Dijkstra算法求下图中顶点0到其他各顶点的最短路径长度,并输出对应的最短路径。


       假设数据输入时采用如下的格式进行输入:首先输入顶点个数n,然后输入每条边的数据。每条边的数据格式为:u v w,分别表示这条边的起点、终点和边上的权值。顶点序号从0开始计起。最后一行为-1 -1 -1,表示输入数据的结束。


#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int MAXN  = 20;const int INF = 1000010;int dist[MAXN];int path[MAXN];int S[MAXN];int Edge[MAXN][MAXN];int n;void Dijkstra(int v0){int i, j;memset(dist, 0, sizeof(dist));for (i = 0; i < n; ++i){dist[i] = Edge[v0][i];//初始时dist中存放v0所在的行S[i] = 0;if (i != v0 && dist[i] < INF)path[i] = v0;elsepath[i] = -1;}S[v0] = 1, dist[v0] = 0;//只有v0 在S中for (i = 0; i < n-1; ++i){int MIN = INF, v = v0;for (j = 0; j < n; ++j){if ( !S[j] && MIN > dist[j] )//在T中找具有最短路径的定点v{MIN  = dist[j];v = j;}}S[v] = 1;//表示v已经加入进来for (j = 0; j < n; ++j)//由于v的加入,可能会导致v0到T中顶点dist[]值“缩短”,如果dist的值修改自然也要修改path{if (!S[j] && Edge[v][j] < INF && (dist[v] + Edge[v][j] < dist[j])){dist[j] = dist[v] + Edge[v][j];path[j] = v;}}}}int main(){int i, j;int u, v, w;cin>>n;while (1){cin>>u>>v>>w;if(u == -1 && v == -1 && w == -1)break;Edge[u][v] = w;}for (i = 0; i < n; ++i){for (j = 0; j < n; ++j){if(i == j)Edge[i][j] = 0;else if(Edge[i][j] == 0)Edge[i][j] = INF;}}Dijkstra( 0 );int shortest[MAXN];for (i = 1; i < n; ++i){cout<<dist[i]<<"\t";memset(shortest, 0, sizeof(shortest));//找到从v0到i的最短路径上的点int k = 0;shortest[k] = i;while (path[ shortest[k] ] != 0){k++;shortest[k] = path[ shortest[k-1] ];}k++;shortest[k] = 0;for(j = k; j > 0; --j)cout<<shortest[j]<<" -> ";cout<<shortest[0]<<endl;}return 0;}

dijkstra与Prim算法有很大的相似性,Prim中lowcost存放的是T中各个顶点到S中各个顶点的权值最小值,而修改的时候,lowcost[k] = min{lowcost[k], Edge[v][k]}

原创粉丝点击