Dijkstra 算法:思路详解 & 代码实现

  • 文章中算法的理论知识、示例以及图片来自《最短路径问题—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] 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值