单源最短路径---Dijkstra算法
有这样一道题:在一个图(如图所示)中,一共有四个点:1 2 3 4
这四个点之间各有相连,且每条边都有自己的权值。现在小明在点1上,
他想要到3去,请问最短路径是多少。
很容易得到该图的邻接矩阵。我们建立一个二维数组a。a[i][j],i表示
起点,为行,j表示终点,为列。将相应的权值传入其中,如果从一个
点到另一个点不通,就认为其权值为无限
例如(1-》2)为2,则a[1][2]=2;
而因为2到1不通,就令a[2][1]=∞;
另外a[1][1]之类的起点终点相同的都设为了0;
对这种求点i到点j的最短路径的问题,很难直接求得。通常是要多求一
些多余的量才能得到结果。因为我们必须要做好遍历全图的准备才能比
较或是寻找出其最短路径。
这时候我们来介绍两种算法:
- 一种是Dijkstra算法单源最短路径算法;
- 一种是Floyd多元路径最短算法;
今天只说单源最短路径算法
所谓单源,即求从一个点出发,到其他各点的最短路径,也就是说
如果这个图有n个点,我们要求n-1个路径。
对一个图G来说,它的点集为V,我们要做的就是求出从起点v到V中其
余各点的最短路径。
首先介绍单源最短路径的核心算法:
起点是v,我们知道在整个图中,以v为起点的路径有很多条,有长的。有短的;有的简单,只有一段弧,只有两个点:起点。终点。有的复杂,有好几段弧,起点终点之间隔了好几个节点。
我们要做的就是先找到所有这些从v引出的路径中的最短的那一条(v,…,j1)。
然后通过某种算法(下文中将会介绍)再找出仅长于最短路径的次短路径(v,…,j2),找到以后,(注意:我们把每一次找到的次短路径的终点记录下来,如果下一次找寻的时候遇到以这些点为终点的路径就忽略掉),再找下一条次短路径,再找,再找……
这里有一个辨析:
按照上述步骤,我们依次找到了整张图中(具有不同终点的)最短的几条路径:
(v,…,j1) (v,…,j2) (v,…,j3) …… (v,…,j) ……
这里,如果我们称图中所有以v为起点 以j为终点的路径为j族,那么我们每找到一条次短路径 (v,…,j),这条路径(v,…,j)一定是j族中最短的那条。
为什么呢?按照我们的找法,我们实际上是把整张图里的所有以v为起点的路径按照从短到长的顺序排列起来,然后从第一条路径开始往后检索,如果我们从前到后查找时第一次遇到了以j为终点的路径,记为路径1,接下来往后,我们遇到的每一条属于j族的路径都忽略,从而我们得到了之前的序列。显然路径1就是j族中最短的那一条,也是我们的目标路径之一。
我们 所要求的是点v到其余各点的最短路径,其余各点有n-1个,也就是说,我们有n-1个终点,对应n-1个族。对每个族,都有一个对应的最短路径。我们要做的就是求出每个族的最短路径。
之前说到,我们要把每一次找到的次短路径的终点记录下来,下一次遇到的时候就忽略掉,这可以保证最终的得到的序列都属于不同的族,我们可以建立一个点集S,每找到一条次短路径,就将其终点并入集合S中,下一次找寻路径的时候拿终点与点集S对比,决定是否保留。
就这样,每一次我们都找到一个以j为终点的最短路径,而每一次的终点j又都不同,当找了n-1次时,就完成了单源最短路径查找。
我们已经了解完了整体的思路,所以现在的关键性问题就是如何完成对次短路径的查找。也就是上文中提到的某种算法,它到底是什么呢?
第一步:
一个图中有许多条路径,我们现在在图G中找到以v为起点的最短的那一条路径(v,j)。显然我们可以很容易的的发现,这条最短路径一定是与起点v直接相连的弧,j是v的邻结点。如图所示;
第二步:
接下来,我们来找次短路径,也就是以v为起点的下一条最短的路径。如图所示我们会发现,次短路径要么是弧(v,k)(注:k是v相邻的点,除j外),要么是弧(v,j,k)(k是j紧邻的点)。
这样,我们通过比较可以求出最短的那一条路径(v,k);
然后我们就会猜想,如果按照第二步的做法一直重复下去,不就能依次找到次短路径了吗?
但是,事实上,当我们尝试之后会发现,随着不断地重复查找次短路径的过程,我们不能单纯的像第二次查找那样,因为每一次的查找都会衍生很多分支。使得查找变得复杂。
怎么解决这个问题呢?为了方便理解我引入了一个观测域的概念。
首先看一些定义:
- 点集V 图中所有点的集合
- 点集S 已经找到相应最短路径的终点集合
- 数组D[n] 存储观测域内能观测到的最短路径,算上起点一共n个数值 。比如D[k]对应在观测域中能观测到的,k族中的最短路径。
- 邻接矩阵a[n][n] 存储着相应的权值
如图所示:刚开始时,我立足于v点,观测域为v点的四周,即v的所有邻接点。由邻接矩阵a,更新数组D。此时D中的数为(v,k)的权值(k为v的邻接点)。
随后,我在我观测域中找寻最短的那一条路径(v,j)也就是查找数组D中最小的数,并将j收入集合S中。
如图所示:现在我想找次短路径,现在我清楚,这条次短路径要么是(v,k)(k为观测域中的点,但不属于S)的最短边,要么是通过j点的弧(v,j,k)(k为j的邻接点,但不属于S)的最短边。
我们干脆将j的邻接点全都纳入观测域,同时更新数组D,通过数组D找出次短边(v,j),再将j压入S中。
不断重复该步骤,直到所有的点都入了S,就完成了查找,这时数组D
D[k]就是从v到k的最短路径的长度。如果你想知道具体的路径时只需加个栈就行了。
所以完整的步骤是这样的:
第一步:
初始化点集S,将起点v收入S中。初始化数组D:D[k]=a[v][k];第二步:找寻次短路径。即查找数组D找出观测域中最短路径(v,j):D[j]=min(D[k]|k不属于S)。将j压入点集S中
第三步:将j的邻接点并入观测域,即用j的邻接点更新数组D:
如果D[k]>D[j]+a[j][k] (k为j邻接点,k不属于S)令D[k]=D[j]+a[j][k]如果D[k]>D[j]+a[j][k] (k为j邻接点,k不属于S)就不做操作
然后不断重复第二步和第三步直到找到全部节点为止。
具体实现为:
#include<iostream>
using namespace std;
#define BUTONG 1000000 // 无限大为不通
#define NUM 4 //d点数为4
int a[NUM][NUM]={0,2,6,4,BUTONG,0,3,BUTONG,7,BUTONG,0,1,5,BUTONG,12,0};
#define OK 1
#define ERROR 0
typedef int status;bool finish(bool *S,int n) //是否完成 找寻
{for(int i=0;i<n;i++){if(!S[i])return false;}return true;
}status djs(int n,int t)//a 为数组 n 为点的个数,v为起始点
{//初始化数组vint D[n];for(int i=0;i<n;i++)D[i]=a[t][i];D[t]=0;//初始化已访问数集S;bool S[n];for(int i=0;i<n;i++)S[i]=false;S[t]=true;int j=0;int min=BUTONG;while (!finish(S,n)){ j=0;min=BUTONG;for(int i=0;i<n;i++) //找到观测域中最短路径(v,j) {if(S[i]) continue;if(min>D[i]) {min=D[i];j=i;} } S[j]=true; //将j纳入点集S中 for(int i=0;i<n;i++) //更新观测域 {if(S[i]) continue;if(D[i]>D[j]+a[j][i])D[i]=D[j]+a[j][i]; }}for(int i=0;i<n;i++) //输出 {printf("最短路径是(v,%d)长度是%d\n",i,D[i]);}return OK;
}
int main()
{djs(NUM,1);return 0;}
单源最短路径---Dijkstra算法相关推荐
- 分支限界法:单源最短路径--dijkstra算法
单源最短路径–dijkstra算法 前面已经多次介绍过dijkstra算法是贪心算法,是动态规划,实际上可以从分支限界的角度来理解: 分支限界法 分支限界法,实际上就是回溯法,一般意义的回溯法是基于深 ...
- 数据结构与算法—单源最短路径dijkstra算法
介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...
- 单源最短路径dijkstra算法
介绍 dijkstra算法也是解决单源最短路径问题的一种方法.它要求图中路径都是非负的.而且,它的效率要高于bellman算法. 实现 首先定义图的结点信息和边信息. struct _Node;typ ...
- 单源顶点最短路径java_单源最短路径-Dijkstra 算法
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 问题:求a点到各个点的最短距离,如下图 ...
- JAVA编程求单源最短路径_【算法】单源最短路径——dijkstra算法
一,概念 单源最短路径 给定一个带权有向图G=(V,E),其中每条边的权是一个实数.另外,还给定V中的一个顶点,称为源.要计算从源到其他所有各顶点的最短路径长度.这里的长度就是指路上各边权之和.这个问 ...
- dijkstra 算法_数据结构与算法—单源最短路径dijkstra算法
介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...
- 单源最短路径Dijkstra算法的思想、详细步骤、代码
目录 一.算法思想 二.算法详细步骤 三.伪代码 + C++代码 四.算法复杂度分析 五.算法改进 六.应用案例 一.算法思想 1.Dijkstra 算法是用来求解单源最短路径问题的经典算法,其本质上 ...
- 单源最短路径Dijkstra算法升级:出现多条最短路径,输出之?
文章目录 引言:单条路径的标配算法 进阶:记录多条路径的改进版Dijkstra算法: 1. 对`P[]`数组进行扩充 2. 求最短路径条数 3. 输出所有最短路径 引言:单条路径的标配算法 一个普通. ...
- 单源最短路径(Dijkstra算法)
题目:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=208 #include <iostream> #incl ...
最新文章
- Canvas贝塞尔三级曲线
- 从getmemery()函数看内存管理、函数传参等一系列问题
- .NET面试题解析(04)-类型、方法与继承
- etcd nginx 容器_Etcd+Confd实现Nginx配置文件自动管理
- freemarker开发指南
- 16. JavaScript Boolean(逻辑)对象
- HOJ 2739 The Chinese Postman Problem
- Git(9):通俗易懂的Git指令
- MTK机型刷机授权 固件转换 分区提取 nv备份 恢复工具教程
- nuxt解决首屏加载慢问题_Vue首屏加载慢
- 文件上传/JS/MIME/黑名单/白名单/htaccess/00截断详解篇[代码审计]
- onmouseover和onmouseout的烦恼
- Lytro Illum光场图像分解的白图像
- php的内置函数strrpos_PHP函数用法详解【初始化、嵌套、内置函数等】
- VM虚拟机 系统出现鼠标定位不准确、双鼠标问题
- 如何在Android中使用Realm数据库
- 第六届《项目管理、敏捷转型、产品创新》智者论坛—深圳站
- 外汇交易平台怎么选择?
- 计算机网络代表着第几次革命,互联网是第几次信息革命
- 正则校验非中文 加长度校验