- 文章中算法的理论知识、示例以及图片来自《最短路径问题—Dijkstra算法详解》这篇博文,我尽量写得通俗易懂些,如侵删。
- 欢迎各位道友与在下交流切磋,如有错误欢迎指正。
一、什么是 Dijkstra 算法
Dijkstra 算法用于寻找图上两点的最短路径。根据最短路径经过的点也是最短路径的原理(由矛盾律得出:如果经过点的路径不是最短路径,则整条路径也不是最短),从起点开始,通过一步步寻找到下一个点的最短路径,最终得到到达其他所有点的最短路径。
- 图:顶点和边(带权值)的集合。eg:宿舍(点)—200m—图书馆(点)—500m—教学楼(点)
- 最短路径:从一顶点到其他顶点的路径权值之和最短。
- Dijkstra 算法:
-1、声明数组dis[]来保存原点到各个顶点的最短距离,数组长度为顶点个数,原点到自身距离副赋为0,无法直接到达的点距离赋为无穷大;数组T[]来保存找到最短路径顶点的值,初始化时只有原点值;
2、寻找T[]以外dis[]里最小的值,作为确定最短路径的顶点加入T[],并寻找它的出度,看通过它的路径是否小于目前dis[]的最短路径距离,有则替换dis[]中值;
3、重复2步骤直到T[]中包含所有顶点。
二、示例
初始化dis[]:
寻找第一个最小值10,v3加入T[],访问顶点出度,更新v4值:
寻找第二个最小值30,v5加入T[],访问顶点出度,更新v4、v6值:
寻找第三个最小值50,v4加入T[],访问顶点出度,更新v6值:
寻找第四个最小值60,v6加入T[],访问顶点出度:
可以看出剩最后两个点时,最后一个点可以直接确定为最短路径(因为其他点最短路径已确定,并且调整过dis[]),退出循环。
实验结果
起点 终点 最短路径 长度
v1 v2 无 ∞
v3 {v1,v3} 10
v4 {v1,v5,v4} 50
v5 {v1,v5} 30
v6 {v1,v5,v4,v6} 60
三、代码实现
C++ 版:
/*
编程思路:
main函数:
1.以二维数组保存图的连线信息,二维保存起、止点标号以及权值;
2.调用Dijkstra算法,参数为二维数组以及源点标号;
3.函数返回最短路径,程序结束。
Dijkstra函数:
1.初始化dis[]
2.用temp[][3]来代替dis[]作为算法运作的媒体,1维保存dis[]值,2维作为排序跳过的标志,3维记录上一个点标号
3.做排序、松弛和固定值的循环操作(固定值即在排序时利用标志跳过之前的最短路径点)
4.用递归程序做出路径,将最短路径与值显示在屏幕上(递归原理是访问上一个点标号,是起点则返回,不是起点采用
递归直至到起点返回,调用函数次数反映路径长度)
思路&亮点:
1.对于算法过程中调用函数产生的可用信息利用标志留在了操作体(媒体)上,使运行一次函数不只解决一个问题,反
映的是对程序的总体把握情况
2.不同函数功能尽量分割成不同函数体,采用的是分工组装的思想
3.在画取路径中想到将路径上一点保留在操作体中,利用递归程序直至递至原点而归返
4.对图像的具现化为线段,采用数组储存起点、终点和权值,这不是我想出来的
*/
#include <iostream>
#include <climits>
using namespace std;
#define NUM 6
//递归思想:1.确定结束条件;2.确定中间运行规则,确保最终能达到终止条件
void p(int temp[][3],int d) {
int a = temp[d][2];
if(0==a) {
cout<<"v0--->v"<<d;
return;
}
p(temp,a);
cout<<"--->v"<<d;
return;
}
void songchi(int LJ[][3],int temp[][3],int sc) {
int newPath;
int j;
for(int i=0; i<sizeof(LJ); i++) {
if(sc==LJ[i][0]) {
j = LJ[i][1];
newPath = temp[sc][0]+LJ[i][2];
if(newPath<temp[j][0]) {
temp[j][0]