贪心算法(五)——迪杰斯特拉算法
时间:2022-05-03
本文章向大家介绍贪心算法(五)——迪杰斯特拉算法,主要内容包括问题描述、数据结构、算法步骤、示例、代码实现、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
问题描述
给一个有向无环带权图,并给一个起点,求出该原点到所有顶点的最短路径。
数据结构
- dis: Map<String,Integer> dis; 存储原点s到指定节点的最短路径长度。 key表示节点编号,value表示s到该终止节点的最短路径长度。
- path: Map<String,String> path; 存储以指定结点为终点的最短路径中,该终点的上一个结点的编号。 key表示终点编号,value表示终点的前驱结点编号。
-
S集合 和 V集合
将所有的结点分成两个集合:
- S集合中存储已经计算出最短路径的结点;
- V集合中存储尚未计算出最短路径的结点。
- k结点: 最新选入S集合的结点,即刚刚计算出最短路径的结点。
- mark: Map<String,Boolean> mark; 用于标识指定结点是否已被选入S集合(即是否已经计算出最短路径)。 key为结点编号,value为是否属于S集合。
算法步骤
- 初始化 a)初始化mark:将初始节点s选入S集合; b)初始化dis:将与s结点所有出边的权值写入dis中; c)初始化path:将所有与s结点直接关联的终止结点的path值设为s;
- 遍历dis,找出最短的边,将该边的终点设为k,并纳入S集合中;
- 遍历k的所有出边,并更新dis和path(设与k直接关联的所有结点为j): 若d[k]+w< k,j> 小于 d[j],则: a)d[j]=d[k]+w< k,j> b)path[j]=k;
- 重复步骤2、3,n-2次后停止。(n为结点数量)
示例
代码实现
/**
* 迪杰斯特拉算法
* @ graph:图的邻接表
* @ start:起始结点
*/
void Dijkstra(Map<String,List<ENode>> graph, String start){
// 初始化
Map<String,Integer> dis = new HashMap<>();
Map<String,String> path = new HashMap<>();
Map<String,Boolean> mark = new HashMap<>();
String k = start;
for( String id : graph.keySet ){
dis.put( id, Integer.MAX_VALUE );
path.put( id, null );
mark.put( id, false );
}
for( ENode edge : graph.get(start) ){
dis.put( edge.id, edge.w );
path.put( edge.id, start );
}
mark.put( k, true );
int n = graph.keySet().size();// 图中结点个数
// 进行n-2次扫描,每次选一个结点放入S集合
for( int i=1; i<=n-2; i++ ){
k = selectKfromDis(dis,mark);// 从dis中选尚未访问的最小值作为k
mark.put( k, true );
for( ENode edge : graph.get(k) ){
if ( !mark.get(edge.id) && dis.get(k)+edge.w < dis.get(edge.id) ) {
dis.put( edge.id, dis.get(k)+edge.w );
path.put( edge.id, k );
}
}
}
}
/**
* 从dis中选一条尚未访问过的最短的边
*/
String selectKfromDis( Map<String,Integer> dis, Map<String, Boolean> mark ){
int min = Integer.MAX_VALUE;
String id = null;
for( Map.Entry<String,Integer> entry : dis ){
if ( !mark.get(entry.getKey()) && entry.getValue() < min ) {
min = entry.getValue();
id = entry.getKey();
}
}
return id;
}
- vhr部门管理数据库设计与编程
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(六)
- 权限管理模块中动态加载Vue组件
- axios请求封装和异常统一处理
- SpringSecurity中密码加盐与SpringBoot中异常统一处理
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(二)
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(一)
- Java操作MongoDB
- 初识MongoDB分片
- Linux上安装Redis
- SpringBoot+WebSocket实现在线聊天(二)
- SpringBoot中使用Freemarker构建邮件模板
- SpringBoot中发送QQ邮件
- SpringBoot中使用POI,快速实现Excel导入导出
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 动态规划入门_钱币兑换问题
- Codeforces Round #547 (Div. 3)D. Colored Boots
- JavaScript 性能优化
- 优化循环的方法-循环展开
- 程序性能优化-局部性原理
- Codeforces Round #547 (Div. 3)E. Superhero Battle
- 《动态规划_入门 LIS 问题 》
- 栅格化系统的原理以及实现
- vue-qr二维码插件使用简介
- Codeforces Round #547 (Div. 3)F1. Same Sum Blocks (Easy)
- 手机软键盘弹起导致页面变形的一种解决方案
- Codeforces Round #547 (Div. 3)F2. Same Sum Blocks (Hard)
- 《 动态规划_ 入门_最大连续子序列 》
- docker搭建elasticsearch集群
- 用canvas实现手写签名功能