数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++

数据结构图之三(最短路径--迪杰斯特拉算法)

【1】最短路径

最短路径?别乱想哈,其实就是字面意思,一个带边值的图中从某一个顶点到另外一个顶点的最短路径。

官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径。

并且我们称路径上的第一个顶点为源点,最后一个顶点为终点。

由于非内网图没有边上的权值,所谓的最短路径其实是指两顶点之间经过的边数最少的路径。

别废话了!整点实际的哈,你能很快计算出下图中由源点V0到终点V8的最短路径吗?

【2】迪杰斯特拉算法

迪杰斯特拉算法是按路径长度递增的次序产生最短路径的思路求解。

具体算法及其详细讲解如下:

阅读程序前,先要搞明白几个数组作用:

final[w]=1; 表示V0到Vw顶点已经有最短路径的结果

ShortPathTable[w]; 表示V0到Vw顶点的最短路径权值和

Pathmatirx[w]; 表示V0到Vw顶点的前驱顶点下标值

开始调用算法前,我们需要为案例图创建邻接矩阵图,如下所示:

(1)程序开始运行,final数组是为了标记V0到某顶点是否已经求得最短路径。

  如果V0到Vw已经有结果,那么final[w]=1;

(2)第5~10行,是对数据初始化工作。 此时final数组均赋值为0,表示所有点均未求得最短路径。

  D数组为 {0,1,5,65515,65535,65535,65535,65535,65535}。因为V0与V1和V2的边权值为1和5。

  P数组全为0,表示目前没有路径。

(3)第11行,表示V0至V0路径为0。

  第12行,表示V0点到V0点已经求得最短路径,因此final[0]=1。

  此时final数组为 {1,0,0,0,0,0,0,0,0},此时整个初始化工作完成。

(4)第13~33行为主循环,每次循环求得V0与一个顶点的最短路径。除去V0,因此索引从1开始。

(5)第15~23行,先令min为65535的极大值,通过w控制循环,与D[w]比较找到最小值为min=1,同时确定k=1。

(6)第24行,由k=1可知与V0最近的顶点是V1,并且由D[1]=1知道此时V0到V1的最短路径是1。

  因此再将对应的final[1]设置为1。此时final数组为 {1,1,0,0,0,0,0,0,0}

(7)第25~32行是一循环,此循环甚为关键。

  它的目的是在刚才已经找到V0与V1的最短路径基础之上,对V1与其它顶点的边进行计算,得到V0与它们的当前最短距离,如图所示:

  因为min=1,所以D[2]=5不再是V0到V2的最短路径,现在D[2]=V0->V1->V2=min+3=4, D[3]=V0->V1->V3=min+7=8,

  D[4]=V0->V1->V4=min+5=6,于是D数组当前值为 {0,1,4,8,6,65535,65535,65535,65535}。

  而P[2]=1,P[3]=1,P[4]=1,其表示V0到V2,V3,V4点的最短路径它们的前驱均是V1。

  此时P数组为 {0,0,1,1,1,0,0,0,0}。

(8)新一轮循环,此时i=2。第15~23行,对w循环,注意因为final[0]=1和final[1]=1,由第18行的!final[w]可知:

  V0与V1并不参与最小值的获取。通过循环比较,找到最小值min=4,k=2。

(9)第24行,由k=2,表示已经求出V0到V2的最短路径,并且由D[2]=4知道最短路径距离为4。

  因此将V2对应的final[2]设置为1,此时final数组为 {1,1,1,0,0,0,0,0,0}。

(10)第25~32行,在刚才已经找到V0与V2的最短路径的基础上,对V2与其它顶点的边进行计算,得到V0与它们的最短距离。

  如图所示:

  因为min=4,所以D[4]=6不再是V0到V4的最短距离,现在D[4]=V0->V2->V4=min+1=5,D[5]=V0->V2->V5=min+7=11。

  因此D数组当前值为 {0,1,4,8,5,11,65535,65535,65535,65535}。

  而原本P[4]=1,此时P[4]=2,P[5]=2,它表示的意思是V0到V4和V5的最短路径前驱均为V2。

  此时P数组为 {0,0,1,1,2,2,0,0,0}。

(11)重新再开始一轮循环,此时i=3。第15~23行,通过对w循环比较找到最小值min=5,k=4。

(12)第24行,由k=4表示已经求出V0到V4的最短路径,并且由D[4]=5知道最短路径距离为5。

  因此将V4对应的final[4]设置为1。此时final数组为 {1,1,1,0,1,0,0,0,0}。

(13)第25~32行,对V4与其它顶点的边值进行计算,得到V0与它们的当前最短距离,如图所示:

  因为min=5,所以D[3]=8不再是V0到V3的最短路径,现在D[3]=V0->V4->V3=min+2=7,同理:

  D[5]=V0->V4->V5=min+3=8,D[6]=V0->V4->V6=min+6=11,

  D[7]=V0->V4->V7=min+9=14,因此,D数组当前值为 {0,1,4,7,5,8,11,14,65535}。

  而原本P[3]=1,此时P[3]=4,原本P[5]=2,此时P[5]=4。

  另外P[6],P[7]=4,它表示V0到V3,V5,V6,V7点的最短路径它们的前驱是V4。

  此时P数组值为 {0,0,1,4,2,4,4,4,0}。

(14)之后的循环完全类似。得到最终的结果,如图所示:

  此时final数组为 {1,1,1,1,1,1,1,1,1},它表示所有的顶点均完成了最短路径的查找工作。

  此时D数组为 {0,1,4,7,5,8,10,12,16},它表示V0到各个顶点的最短路径数,比如D[8]=1+3+1+2+3+2+4=16。

  此时的P数组为 {0,0,1,4,2,4,3,6,7}:

  这个P数组值可能难理解一些。比如P[8]=7,它表示要查看V0到V8的最短路径时,顶点V8的前驱是V7;

  再由P[7]=6表示要查看V0到V7的最短路径时,顶点V7的前驱是V6,同理,P[6]=3表示V6的前驱是V3。

  这样就可以得到:V0到V8最短路径为V8<-V7<-V6<-V3<-V4<-V2<-V1<-V0

  即就是: V0->V1->V2->V4->V3->V6->V7->V8。

【3】算法实现

实现代码如下:

  1 #include <iostream>
  2 #include "SeqList.h"
  3 #include "Stack.h"
  4 #include <iomanip>
  5 using namespace std;
  6
  7 #define  INFINITY  65535
  8
  9 template<class NameType, class DistType>
 10 class Graph
 11 {
 12 private:
 13     SeqList<NameType> Vertices;
 14     DistType **Edges;
 15     int nVer, nEdges;
 16
 17 public:
 18     Graph()
 19         : Edges(NULL)
 20         , nEdges(0)
 21         , nVer(0)
 22     {}
 23     ~Graph()
 24     {}
 25
 26 public:
 27     int GetVer() const
 28     {
 29         return nVer;
 30     }
 31
 32     istream & operator>>(istream &in)
 33     {
 34         int v, u, value;
 35         int i, j;
 36         NameType item;
 37         cout << "请输入顶点的个数: " << endl;
 38         in >> nVer;
 39         cout << "请输入顶点的数据信息: " << endl;
 40         for (i = 0; i < nVer; ++i)
 41         {
 42             in >> item;
 43             Vertices.push_back(item);    // 保存全部顶点
 44         }
 45         /////二维数组的创建并初始化
 46         Edges = new DistType*[nVer]; // DistType *ar[10];
 47         for (i = 0; i < nVer; ++i)
 48         {
 49             Edges[i] = new DistType[nVer];
 50             for (j = 0; j < nVer; ++j)
 51             {
 52                 Edges[i][j] = 0;
 53             }
 54         }
 55         cout << "请输入边的个数: " << endl;
 56         in >> nEdges;
 57         cout << "请输入边的信息:" << endl;
 58         for (i = 0; i < nEdges; ++i)
 59         {
 60             in >> v >> u >> value;
 61             Edges[v][u] = value;
 62             Edges[u][v] = value;
 63         }
 64         return in;
 65     }
 66     ostream & operator<<(ostream &out) const
 67     {
 68         int i, j;
 69         out << "顶点信息 " << endl;
 70         for (i = 1; i <= nVer; ++i)
 71         {
 72             out << Vertices[i] << setw(5);
 73         }
 74         out << endl;
 75         out << "矩阵信息:" << endl;
 76         out << setw(10);
 77         for (i = 1; i <= nVer; ++i)
 78         {
 79             out << Vertices[i] << setw(5);
 80         }
 81         out << endl;
 82         for (i = 0; i < nVer; ++i)
 83         {
 84             out << Vertices[i+1] << setw(5);
 85             for (j = 0; j < nVer; ++j)
 86             {
 87                 if (0 == Edges[i][j] && i != j)
 88                     Edges[i][j] = INFINITY;
 89                 cout << Edges[i][j] << setw(5);
 90             }
 91             out << endl;
 92         }
 93         out << endl;
 94
 95         return out;
 96     }
 97     // 迪杰斯特拉算法实现
 98     void ShortestPath_Dijkstra(int v0, int* final, int*p, int *D)
 99     {
100         int v, w, k, min;
101         // 初始化数据
102         for (v = 0; v < nVer; ++v)
103         {
104             final[v] = 0;    // 全部顶点初始化为未知对短路径状态
105             D[v] = Edges[v0][v]; //将与V0点有连线的顶点加上权值
106             p[v] = 0;    // 初始化路径数组p为0
107         }
108         D[v0] = 0;    // V0至V0路径为0
109         final[v0] = 1;    // final[W]=1表示V0至V0不需要求路径
110         // 开始主循环,每次求得V0到某个V顶点的最短路径
111         for (v = 1; v < nVer; ++v)
112         {
113             min = INFINITY;    // 当前所知离V0顶点最近距离
114             for (w = 0; w < nVer; ++w) // 寻找离V0最近的顶点
115             {
116                 if (!final[w] && D[w] < min)
117                 {
118                     min = D[w]; // w顶点离V0顶点更近
119                     k = w;
120                 }
121             }
122
123             final[k] = 1; // 将目前找到的最近的顶点置为1
124             for (w = 0; w < nVer; ++w) // 修正当前最短路径距离
125             {
126                 // 如果经过V顶点的路径比现在这条路径的长度短的话
127                 if (!final[w] && (min + Edges[k][w] < D[w]))
128                 {
129                     // 说明找到了最短的路径,修改D[w] 和 p[w]
130                     D[w] = min + Edges[k][w]; // 修改当前路径长度
131                     p[w] = k;
132                 }
133             }
134         }
135     }
136 };
137
138 template<class NameType, class DistType>
139 istream & operator>>(istream &in, Graph<NameType,DistType> &g)
140 {
141     g >> in;
142     return in;
143 }
144
145 template<class NameType, class DistType>
146 ostream & operator<<(ostream &out, const Graph<NameType,DistType> &g)
147 {
148     g << out;
149     return out;
150 }
151
152 void main()
153 {
154     Graph<char, int> myg;
155     cin >> myg;
156     cout << "打印所有输入信息:" << endl;
157     cout << myg << endl;
158     cout << "求最短路径....." << endl;
159     int numVer = myg.GetVer();
160     int* pFinal = new int[numVer];
161     int* pPathmatirx = new int[numVer];
162     int* pShortPath = new int[numVer];
163     myg.ShortestPath_Dijkstra(0, pFinal, pPathmatirx, pShortPath);
164     cout << "打印各顶点最短路径标记数组值:" << " ";
165     for (int i = 0; i < numVer; ++i)
166     {
167         cout << pFinal[i] << " ";
168     }
169     cout << endl;
170     cout << "打印最短路径数组值:" << " ";
171     for (int i = 0; i < numVer; ++i)
172     {
173         cout << pShortPath[i] << " ";
174     }
175     cout << endl;
176     cout << "打印最短路径前驱数组值:" << " ";
177     for (int i = 0; i < numVer; ++i)
178     {
179         cout << pPathmatirx[i] << " ";
180     }
181     cout << endl;
182     cout << "打印V0到各个顶点最短路径值以及路径信息:" << endl;
183     SeqStack<int> sQ;
184     for (int i = 1; i < numVer; ++i)
185     {
186         cout << "V0~V" << i << ": " << pShortPath[i] << endl;
187
188         sQ.Push(pPathmatirx[i]);
189         int n = 0;
190         while (sQ.GetTop(n) && n != 0)
191         {
192             sQ.Push(pPathmatirx[n]);
193         }
194
195         while (!sQ.IsEmpty())
196         {
197             int m = 0;
198             sQ.Pop(m);
199             cout << "V" << m << "->";
200         }
201         cout << "V" << i << endl;
202     }
203     delete []pFinal;
204     delete []pPathmatirx;
205     delete []pShortPath;
206     pFinal = NULL;
207     pPathmatirx = NULL;
208     pShortPath = NULL;
209 }
210 // 备注:
211 // 最短路径迪杰斯特拉算法实现
212 // 整理于2013-12-04
213 // 测试输入程序为:
214 /*
215 请输入顶点的个数:
216 9
217 请输入顶点的数据信息:
218 A B C D E F G H I
219 请输入边的个数:
220 16
221 请输入边的信息:
222 0 1 1
223 0 2 5
224 1 2 3
225 1 3 7
226 1 4 5
227 2 4 1
228 2 5 7
229 3 4 2
230 3 6 3
231 4 5 3
232 4 6 6
233 4 7 9
234 5 7 5
235 6 7 2
236 6 8 7
237 7 8 4
238 打印所有输入信息:
239 顶点信息
240 A    B    C    D    E    F    G    H    I
241 矩阵信息:
242 A    B    C    D    E    F    G    H    I
243 A    0    1    5655356553565535655356553565535
244 B    1    0    3    7    565535655356553565535
245 C    5    3    065535    1    7655356553565535
246 D65535    765535    0    265535    36553565535
247 E65535    5    1    2    0    3    6    965535
248 F6553565535    765535    3    065535    565535
249 G655356553565535    3    665535    0    2    7
250 H65535655356553565535    9    5    2    0    4
251 I655356553565535655356553565535    7    4    0
252
253
254 求最短路径.....
255 打印各顶点最短路径标记数组值: 1 1 1 1 1 1 1 1 1
256 打印最短路径数组值: 0 1 4 7 5 8 10 12 16
257 打印最短路径前驱数组值: 0 0 1 4 2 4 3 6 7
258 打印V0到各个顶点最短路径值以及路径信息:
259 V0~V1: 1
260 V0->V1
261 V0~V2: 4
262 V0->V1->V2
263 V0~V3: 7
264 V0->V1->V2->V4->V3
265 V0~V4: 5
266 V0->V1->V2->V4
267 V0~V5: 8
268 V0->V1->V2->V4->V5
269 V0~V6: 10
270 V0->V1->V2->V4->V3->V6
271 V0~V7: 12
272 V0->V1->V2->V4->V3->V6->V7
273 V0~V8: 16
274 V0->V1->V2->V4->V3->V6->V7->V8
275  */

关于实现代码中的SeqList.h文件和Stack.h文件从随笔《顺序表》和《》中查找拷贝一份即可。调试环境为VS2010。

Good  Good  Study, Day  Day Up.

顺序  选择  循环  总结

时间: 2024-10-06 14:39:48

数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++的相关文章

最短路径---迪杰斯特拉算法[图中一个顶点到其他顶点的最短距离]

转自大神:https://www.cnblogs.com/skywang12345/p/3711512.html 是真的牛逼 看大神的吧 舒服点  我注释了点最后代码的部分 迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用

[从今天开始修炼数据结构]图的最短路径 —— 迪杰斯特拉算法和弗洛伊德算法的详解与Java实现

在网图和非网图中,最短路径的含义不同.非网图中边上没有权值,所谓的最短路径,其实就是两顶点之间经过的边数最少的路径:而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,我们称路径上第一个顶点是源点,最后一个顶点是终点. 我们讲解两种求最短路径的算法.第一种,从某个源点到其余各顶点的最短路径问题. 1,迪杰斯特拉(Dijkstra)算法 迪杰斯特拉算法是一个按路径长度递增的次序产生最短路径的算法,每次找到一个距离V0最短的点,不断将这个点的邻接点加入判断,更新新加入的点到V0的距

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

和 普利姆算法 思想有点像 还是搞不懂到底p数组到底有什么用 #include<cstdio> #include<cstring> #include<cstdlib> #define MAXVEX 9 #define INFINITY 655 typedef struct { char vexs[MAXVEX]; int matirx[MAXVEX][MAXVEX]; int numVextexes,numEdges; }MGraph; void ShortestPat

数据结构之单源最短路径(迪杰斯特拉算法)-(九)

最开始接触最短路径是在数据结构中图的那个章节中.运用到实际中就是我在大三参加的一次美赛中,解决中国的水资源问题.所谓单源最短路径,就是一个起点到图中其他节点的最短路径,这是一个贪心算法. 迪杰斯特拉算法原理(百科): 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增的次序加入到S中,保证: (1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度 (2)每个顶

数据结构之最短路径(1) [迪杰斯特拉算法]

迪杰斯特拉算法介绍: 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想: 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且

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

图结构中应用的最多的就是最短路径的查找了,关于最短路径查找的算法主要有两种:迪杰斯特拉算法(Dijkstra)和Floyd算法. 其中迪杰斯特拉算法(Dijkstra)实现如下: 原理就是不断寻找当前的最优解: void main() { int V[Max][Max]={0,8,32,Infinity,Infinity, 12,0,16,15,Infinity, Infinity,29,0,Infinity,13, Infinity,21,Infinity,0,7, Infinity,Infi

图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP

文转:http://blog.csdn.net/zxq2574043697/article/details/9451887 一: 最短路径算法 1. 迪杰斯特拉算法 2. 弗洛伊德算法 二: 1. 迪杰斯特拉算法 求从源点到其余各点的最短路径 依最短路径的长度递增的次序求得各条路径 路径长度最短的最短路径的特点: 在这条路径上,必定只含一条弧,并且这条弧的权值最小. 下一条路径长度次短的最短路径的特点: 它只可能有两种情况:或是直接从源点到该点(只含一条弧):或者是从源点经过顶点v1,再到达该顶

算法-迪杰斯特拉算法(dijkstra)-最短路径

迪杰斯特拉算法(dijkstra)-最短路径 简介: 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 算法思想: 设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中

最短路径之迪杰斯特拉算法(Dijkstra)

1.迪杰斯特拉(dijkstra)算法简介 Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式, 是目前公认的最好的求解最短路径的方法.算法解决的是有向图中单个源点到其他顶点的最短 路径问题,其主要特点是每次迭代时选择的下一个顶点是标记点之外距离源点最近的顶点.但 由于dijkstra算法主要计算从源点到其他所有点的最短路径,所以算法的效率较低. 2.dijkstra算法基本过程 假设路网中每一个节点都有标号 是从出发点s到点t的最短路径长