最短路径——迪杰斯特拉算法

来源:互联网 发布:什么社交软件好 编辑:程序博客网 时间:2024/06/05 07:18

概述
用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
算法
按路径长度递增次序产生算法:
把顶点集合V分成两组:
(1)S:已求出的顶点的集合(初始时只含有源点V0)
(2)V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,保证:
(1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
(2)每个顶点对应一个距离值
S中顶点:从V0到此顶点的长度
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度
依据:可以证明V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和
(反证法可证)
求最短路径步骤
算法步骤如下:
G={V,E}
1. 初始时令 S={V0},T=V-S={其余顶点},<V0,Vi>,d(V0,Vi)V0,Vi>弧上的权值
若存在<V0,Vi>,d(V0,Vi)<V0,Vi>弧上的权值
若不存在<V0,Vi>,d(V0,Vi)为∞
2. 从T中选取一个与S中顶点有关联边且权值最小的顶点W,加入到S中
3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值
重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止

<<数据结构>>(C语言版 严蔚敏 吴为民 编著) 中该算法的实现

/*测试数据 教科书 P189 G6 的邻接矩阵 其中 数字 1000000 代表无穷大61000000 1000000 10 100000 30 1001000000 1000000 5 1000000 1000000 10000001000000 1000000 1000000 50 1000000 10000001000000 1000000 1000000 1000000 1000000 101000000 1000000 1000000 20 1000000 601000000 1000000 1000000 1000000 1000000 1000000结果:D[0]   D[1]   D[2]   D[3]   D[4]   D[5] 0   1000000   10     50     30     60*/#include <iostream>#include <cstdio>#define MAX 1000000using namespace std;int arcs[10][10];//邻接矩阵int D[10];//保存最短路径长度int p[10][10];//路径int final[10];//若final[i] = 1则说明 顶点vi已在集合S中int n = 0;//顶点个数int v0 = 0;//源点int v,w;void ShortestPath_DIJ(){     for (v = 0; v < n; v++) //循环 初始化     {          final[v] = 0; D[v] = arcs[v0][v];          for (w = 0; w < n; w++) p[v][w] = 0;//设空路径          if (D[v] < MAX) {p[v][v0] = 1; p[v][v] = 1;}     }     D[v0] = 0; final[v0]=0; //初始化 v0顶点属于集合S     //开始主循环 每次求得v0到某个顶点v的最短路径 并加v到集合S中     for (int i = 1; i < n; i++)     {          int min = MAX;          for (w = 0; w < n; w++)          {               //我认为的核心过程--选点               if (!final[w]) //如果w顶点在V-S中               {                    //这个过程最终选出的点 应该是选出当前V-S中与S有关联边                    //且权值最小的顶点 书上描述为 当前离V0最近的点                    if (D[w] < min) {v = w; min = D[w];}               }          }          final[v] = 1; //选出该点后加入到合集S中          for (w = 0; w < n; w++)//更新当前最短路径和距离          {               /*在此循环中 v为当前刚选入集合S中的点               则以点V为中间点 考察 d0v+dvw 是否小于 D[w] 如果小于 则更新               比如加进点 3 则若要考察 D[5] 是否要更新 就 判断 d(v0-v3) + d(v3-v5) 的和是否小于D[5]               */               if (!final[w] && (min+arcs[v][w]<D[w]))               {                    D[w] = min + arcs[v][w];                   // p[w] = p[v];                    p[w][w] = 1; //p[w] = p[v] + [w]               }          }     }}int main(){    cin >> n;    for (int i = 0; i < n; i++)    {         for (int j = 0; j < n; j++)         {              cin >> arcs[i][j];         }    }    ShortestPath_DIJ();    for (int i = 0; i < n; i++) printf("D[%d] = %d\n",i,D[i]);    return 0;}
0 0
原创粉丝点击