1 Dijkstra算法

1.1 算法基本信息

  • 解决问题/提出背景

    • 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径)
  • 算法思想

    • 贪心算法

      • 按路径长度递增的次序,依次产生最短路径的算法
    • 【适用范围】Dijkstra算法仅适用于【权重为正】的图模型中
  • 时间复杂度

    • O(n^3)
  • 补充说明

    • 亦可应用于【多源最短路径】(推荐:Floyd算法(动态规划,O(n^3)))

      • Dijkstra 时间复杂度: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语言版/ 严蔚敏 李冬梅 吴伟民 编)》

最新文章

  1. iOS计算完整文字高度(适应iOS 10)
  2. Autodesk的照片建模云服务—Autodesk ReCap 360 photo
  3. Linux 相关基础笔记
  4. memcached使用详解
  5. Vim+Ctags+Taglist组合:
  6. 淘宝店铺应用android源码
  7. jquery日历datepicker的使用方法
  8. 编写一个方法,输入DOM节点,返回包含所有父节点的一个数组
  9. 【Cocos2d-x】Mac 在 Cocos2d-x 3.X 打包Android
  10. Linux 中出现的-bash: syntax error near unexpected token `
  11. UNIX环境高级编程——线程和fork
  12. Visual Studio 和 c# 正则表达式
  13. SAP MM已经转成PO的采购申请Item依旧可以被删除?
  14. json和jquery中的ajax
  15. SVN的工作原理及流程手册
  16. Jeesite 代码生成
  17. 02-Unity深入浅出(二)
  18. 如何查看yum 安装的软件路径
  19. 搭建 Guacamole 并解决各种坑和创建不了虚拟驱动器导致无法实现文件传输的方法
  20. windows系统正常但linux系统下找不到文件的问题

热门文章

  1. v-solt插槽
  2. JAVA遇见HTML——JSP篇:JSP内置对象(下)
  3. onbeforeunload、onpagehide、onunload、onload、onpageshow的正确执行顺序
  4. jQuery获取父窗口的元素
  5. 第六章 Flask-WTF(二)
  6. date对象获取get
  7. CentOS:去掉警报声音
  8. P1169 [ZJOI2007]棋盘制作 悬线法or单调栈
  9. Activiti服务类- HistoryService服务类
  10. java中vector中add,addElement区别