[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)
1 Dijkstra算法
1.1 算法基本信息
解决问题/提出背景
- 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径)
算法思想
- 贪心算法
- 按路径长度递增的次序,依次产生最短路径的算法
- 【适用范围】Dijkstra算法仅适用于【权重为正】的图模型中
- 贪心算法
时间复杂度
- O(n^3)
补充说明
- 亦可应用于【多源最短路径】(推荐:Floyd算法(动态规划,O(n^3)))
- Dijkstra 时间复杂度:O(n^3)
- 亦可应用于【多源最短路径】(推荐:Floyd算法(动态规划,O(n^3)))
1.2 算法描述
- 1.2.1 求解过程(具体思路)
- 1.2.2 示例
1.2 编程复现
- 1> 定义图模型(邻接矩阵表示法)的【基本存储结构体】
# define MaxInt 32767 // 表示极大值 即 ∞ (无穷大)
# define MVNum 100 // 最大顶点数
typedef int VertexType; // 假设顶点的数据类型为整型
typedef int ArcType; // 假设Vi与Vj之边的权值类型为整型
typedef struct {
VertexType vexs[MVNum]; // 顶点表 (存储顶点信息)
ArcType arcs[MVNum][MVNum]; // 邻接矩阵
int vexnum,arcnum; // 图的当前顶点数与边数
}AMGraph; // Adjacent Matrix Graph 邻接矩阵图
- 2> 定义 Dijkstra 算法的【辅助数据结构体】
bool S[MVNum]; // S[i] 记录从源点V0到终点Vi是否已被确定为最短路径长度 【划分确定与未确定: 跟贪心算法的适用范围(不可取消性)有直接联系】
// true:表已确定;false:表尚未确定
ArcType D[MVNum]; // D[i] 记录从源点V0到终点Vi的【当前】最短路径【长度】
int Path[MVNum]; // Path[i] 记录从源点V0到终点Vi的【当前】最短路径上【Vi的[直接前驱]的顶点序号】
- 3> 初始化(邻接矩阵)带权有向图的图模型
void InitAMGraph(AMGraph &G){
cout<<"Please Input Vertexs Number:";
cin>>G.vexnum;
cout<<"\nPlease Directed Edges Number:";
cin>>G.arcnum;
for(int i=0;i<MVNum;i++){
for(int j=0;j<MVNum;j++){
if(i!=j){ // 【易错】 初始化<Vi, Vj>时: <Vi,Vj> 路径长度无穷大 (i!=j)
G.arcs[i][j] = MaxInt;
} else { // 【易错】 初始化<Vi, Vj>时: <Vi,Vi>【自回环】路径长度为0 (i==i)
G.arcs[i][j] = 0;
}
}
}
for(int i=0;i<G.vexnum;i++){
G.vexs[i] = i;
}
cout<<"\nPlease Input All Directed Edges and their Weight now:";
cout<<"\nDirected Edges(i,j,weight): "<<endl;
int i,j;
int weight;
for(int k=0;k<G.arcnum;k++){
// cout<<"("<<(k+1)<<") ";
cin>>i;cin>>j;cin>>weight;
G.arcs[i][j] = weight;
}
cout<<endl;
}
- 4> Dijkstra算法:求解单源最短路径
void ShortestPath_Dijkstra(AMGraph G, int V0){
//step1 n个顶点依次初始化
int n =G.vexnum;
for(int v=0;v<n;v++){
S[v] = false;
D[v] = G.arcs[V0][v];
if(D[v]<MaxInt){
Path[v] = V0;
} else {
Path[v] = -1;
}
}
//step2 将源点V0划入已确定集合S中
S[V0] = true;
D[V0] = 0; // 源点V0到源点V0的最短路径长度必然为0
//step3 贪心算法策略:
// 3.1 循环遍历所有结点:
// 3.2 先确定当前最短路径的终点v;
// 3.3 然后,将v划入已确定集合S中;
// 3.4 最后,以利用结点v更新所有尚未确定的结点的最短路径
int v;
int min;
D[G.vexnum] = MaxInt;
for(int i=1;i<n;i++){//3.1循环遍历所有结点 (即 求从源点V0到图中每一顶点(共计n-1个顶点)的最短路径)
//3.2 确定当前最短路径的终点v;
min = MaxInt;
for(int w=0;w<n;w++){
if(S[w]==false && D[w]<min){//比本轮循环中,已知的最短路径还短 【易错/易漏】 S[w]==false : 必须满足当前结点 Vw 属于尚未确定的结点
v = w;
min = D[w];
}
}
//3.3 然后,将v划入已确定集合S中;
S[v] = true;
//3.4 最后,以利用结点v更新所有尚未确定的结点的最短路径
for(int w=0;w<n;w++){
//↓更新Vw结点的最短路径长度为 D[v] + G.arcs[v][w]
//cout<<"S["<<w<<"]:"<<S[w]<<"D["<<v<<"]"<<D[v]<<"G.arcs["<<v<<"]["<<w<<"]"<<"D["<<w<<"]"<<D[w]<<endl;
if(S[w]==false && (D[v] + G.arcs[v][w] < D[w])){//【易错/易漏】 S[w]==false : 必须满足当前结点 Vw 属于尚未确定的结点
D[w] = D[v] + G.arcs[v][w];
Path[w] = v; // 更新 结点Vw的前驱为 v
}
}
v = G.vexnum;
}
}
- 5> 输出结果 D[i]、Path[j]
void OutputD(AMGraph G, int V0){
cout<<"Shortest Distance Weight of the Pair of Directed Vertices("<<V0<<", j):"<<endl;
for(int j=0;j<G.vexnum;j++){
cout<<D[j]<<"\t";
}
cout<<endl;
}
void OutputPath(AMGraph G,int V0){
cout<<"Shortest Distance Path("<<V0<<",j) of the Pair of Directed Vertices:"<<endl;
for(int j=0;j<G.vexnum;j++){
cout<<Path[j]<<"\t";
}
cout<<endl;
}
- 6> 执行:Main函数
int main(){
int V0; //源点V0的下标
AMGraph G;
InitAMGraph(G);
cout<<"Please Input the Index of Source Node 'V0':";
cin>>V0;
ShortestPath_Dijkstra(G, V0);
OutputD(G, V0);
OutputPath(G, V0);
return 0;
}
- 7> Test: Output of Main
Please Input Vertexs Number:6
Please Directed Edges Number:8
Please Input All Directed Edges and their Weight now:
Directed Edges(i,j,weight):
1 2 5
0 2 10
3 5 10
4 3 20
0 4 30
2 3 50
4 5 60
0 5 100
Please Input the Index of Source Node 'V0':0
Shortest Distance Weight of the Pair of Directed Vertices(0, j):
0 32767 10 50 30 60
Shortest Distance Path(0,j) of the Pair of Directed Vertices:
0 -1 0 4 0 3
2 参考文献
- 《数据结构(C语言版/ 严蔚敏 李冬梅 吴伟民 编)》
[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)的更多相关文章
- 图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)
文字描述 引言:如下图一个交通系统,从A城到B城,有些旅客可能关心途中中转次数最少的路线,有些旅客更关心的是节省交通费用,而对于司机,里程和速度则是更感兴趣的信息.上面这些问题,都可以转化为求图中,两 ...
- 单源最短路径-迪杰斯特拉算法(Dijkstra's algorithm)
Dijkstra's algorithm 迪杰斯特拉算法是目前已知的解决单源最短路径问题的最快算法. 单源(single source)最短路径,就是从一个源点出发,考察它到任意顶点所经过的边的权重之 ...
- 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析
什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...
- 最短路径-迪杰斯特拉(dijkstra)算法及优化详解
简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...
- 最短路径 - 迪杰斯特拉(Dijkstra)算法
对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...
- JS实现最短路径之迪杰斯特拉(Dijkstra)算法
最短路径: 对于网图来说,最短路径是指两个顶点之间经过的边上权值和最少的路径,我们称第一个顶点是源点,最后一个顶点是终点 迪杰斯特拉 ( Dijkstra) 算法是并不是一下子就求出 了 Vo 到V8 ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...
- 迪杰斯特拉Dijkstra算法介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...
- [从今天开始修炼数据结构]图的最短路径 —— 迪杰斯特拉算法和弗洛伊德算法的详解与Java实现
在网图和非网图中,最短路径的含义不同.非网图中边上没有权值,所谓的最短路径,其实就是两顶点之间经过的边数最少的路径:而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,我们称路径上第 ...
- 数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++
数据结构图之三(最短路径--迪杰斯特拉算法) [1]最短路径 最短路径?别乱想哈,其实就是字面意思,一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两 ...
随机推荐
- 标准库类型之vector
上篇中遗留了一个小作业,就是用string中的find_first_not_of和find_last_not_of函数来实现字符串左右空格的去除,先来完成它,实现的思路是先来编写去除左空格,然后再编写 ...
- HDU 6741 树上删叶子节点博弈
假设现在有一颗树A 我们在他非叶子节点上加一个点变成树B 则此时树B必为先手必胜 假设A为先手必胜 则先手直接把加入的点一同删去 假设A为先手必败 则先手可以只删加入的点 与后手位置互换 把必败态留给 ...
- PHP数组赋值
<?php $array1 = array('a','b'); $array2 = array('a'=>array('1','2'),'b'=>array('3','4')); $ ...
- PHP程序员的技术成长规划(转载)
按照了解的很多PHP/LNMP程序员的发展轨迹,结合个人经验体会,抽象出很多程序员对未来的迷漫,特别对技术学习的盲目和慌乱,简单梳理了这个每个阶段PHP程序员的技术要求,来帮助很多PHP程序做对照设定 ...
- Maya cmds polyOptions() 获取和设置 mesh 的属性
Maya cmds polyOptions() 获取和设置 mesh 的属性 举例: cmds.polyOptions(dt = True) # 显示所有选择的 mesh 的三角化线(四边形的对角虚线 ...
- pip报错:解决pkg_resources.DistributionNotFound: The 'pip==7.1.0' distribution was not found and is required by the application
如果pip安装后提示依然没有pip命令,需在在添加环境变量 # vim /etc/profile 在文档最后,添加: export PATH="/usr/local/python2.7/bi ...
- 6、组件注册-@Lazy-bean懒加载
6.组件注册-@Lazy-bean懒加载 懒加载:单实例bean,默认是在容器启动的时候创建对象:懒加载就是启动的是不创建,在第一次使用的时候再创建对象. @Lazy // 单实例下懒加载bean
- 怎么学好js
Js给人那种感觉的原因多半是因为它如下的特点: A:本身知识很抽象.晦涩难懂,如:闭包.内置对象.DOM. B:本身内容很多,如函数库.对象库就一大堆. C:混合多种编程思想.它里面不但牵涉面向过程编 ...
- 本地启动服务,两个进程分别监听两个端口,导致两个 URL 不同
问题描述: 本地启了两个服务:A(http://localhost:8001) B(http://localhost:8000),A 项目要怎么才能关联到 B 项目,也就是 A 项目请求怎么跳到 B ...
- P2680 运输计划 二分+树上差分
又咕咕了几天\(QwQ\) 思路:二分+树上差分 提交:\(\geq5\)次 错因:\(lca\)写错+卡了很久常数(哪位大佬帮我康康,有更好的写法请指出\(QwQ\)) 题解: 我们先将原问题转化为 ...