算法用途

  • 找出加权图中前往X的最短路径

并不单指距离,只要能转换成有向图并且边存在权重的情况都适用,当然边的权重不能存在负值

算法思想

  • 找最小花销的节点
  • 更新该节点邻居的最小花销
  • 重复上述过程直到遍历完图中全部的节点
  • 得出最终路径

算法实例

Rama想拿乐谱换架钢琴,Alex愿意拿海报换Rama的乐谱,如果+5元还可以换Alex的唱片;Amy愿意拿出吉他或者架子鼓换海报或者唱片,唱片+15得吉他,唱片+20得架子鼓,海报+30得吉他,海报+35得架子鼓;Beethoven愿意拿出钢琴换Amy的吉他或者架子鼓,吉他+20得钢琴,架子鼓+10得钢琴;

解题思路

1.将题目转换成图

2.根据图生成3张表

第一张表记录节点间的相邻关系和权重,别名graph(方便后续论述)

乐谱 唱片 5
海报 0
唱片 吉他 15
20
海报 吉他 30
35
吉他 钢琴 20
钢琴 10

第二张表记录图的起点到各个节点的最小开销表,别名cost

乐谱 唱片 5
海报 0

目前仅知起点到唱片和海报的最小开销,其余节点需要计算得出

第三张表记录各个节点在最小开销的情况下父节点的名称,别名parent

节点 父节点
唱片 乐谱
海报 乐谱

因为目前仅知唱片和海报的最小开销,其余节点需在计算时保存父节点名称

3.结合上述三张表应用算法思想

  • 找最小花销的节点,即寻找cost表中开销数字最小的,那么我们找到了海报这个节点
  • 海报的邻居从graph表中可以知道为吉他和鼓,那么吉他的开销=30(graph[海报][吉他])+0(cost[乐谱][海报])=30;同理可得鼓的开销。那么它们是不是最小开销呢?因为我们的cost表是用来记录最小开销的,所以需要和cost中的值进行对比,如果小于cost表中的值即为最小开销。遍历cost表可知没有这两个节点,那么它们即为最小开销。
  • 更新cost表记录当前吉他和鼓的最小开销
  • 更新parent表记录当前吉他和鼓在取得最小开销时的父节点名称(目前是海报)

记得标记海报为已处理节点,这样再次从cost表中寻找最小开销节点时便不用考虑海报了

  • 重复上述过程,寻找cost表开销最小的节点,找到了唱片,开销为5
  • 通过graph表得知唱片的邻居节点也是吉他和鼓,计算它们的开销分别为graph[唱片][吉他]+cost[乐谱][唱片]=20;graph[唱片][鼓]+cost[乐谱][唱片]=25;小于cost表中的30,35,所以它们是最小开销
  • 更新cost表,将吉他和鼓的最小开销更新为20,25
  • 更新parent表记录当前吉他和鼓在取得最小开销时的父节点名称(目前是唱片)

记得标记唱片为已处理节点,这样再次从cost表中寻找最小开销节点时便不用考虑唱片了

  • ....一直重复上述过程直到cost中的节点全部遍历完

根据上述过程我们了解到Dijkstra的每一步其实都是在更新cost表,记录各个节点的最小开销,最后一步一定是记录终点的最小开销。这种每一次过程其实也可以认为是在求最优解,所以它也是贪心算法的一种。

避雷

  • Dijkstra不适用于图上有负权边的情况

我在上图中唱片与海报间加一条负权边

我们现在重复上述解题思路,生成三张表,graph表多一条记录graph[唱片][海报]=-7,而cost表和parent表都是不变的!!!这就导致了问题,其实我们知道现在cost[海报]应该的等于-2才是最小开销而不是0,但是在最开始的cost表里仍然记录了0,然后我们开始计算:

  • 遍历cost表中的最小开销,海报为0;找到邻居节点吉他和鼓,计算吉他和鼓的开销
  • 更新吉他和鼓的最小开销
  • 更新parent表记录当前吉他和鼓在取得最小开销时的父节点名称(目前是海报)
  • 标记海报为已处理节点!!!!!!到此海报节点已经被处理完毕了,它的最小开销被永远的记录为0,这与现实情况不符,而贪心算法后续的最优解一定是建立在前面已处理节点是最优解的基础上,所以后面的节点最小开销也会计算错误

PS:作者看的算法图解一书中提出Dijkstra不能用于有向环图,我一直不明白,自己模拟有环的数据也是能求出最短路径的,所以暂且认为Dijkstra是可以处理有向环图的。

实现源码

package mainimport "fmt"func main(){//定义graph字典graph := map[string]map[string]int{"music":{"albumn":5,"post":0},"albumn":{"post":2,"guitar":15,"drum":20},"post":{"music":1,"guitar":30,"drum":35},"guitar":{"piano":20},"drum":{"piano":10},}//定义开销字典cost := map[string]int{"albumn":5,"post":0}//定义存储父节点的字典parent :=map[string]string{"albumn":"music","post":"music"}//存储已经处理过的节点handled := make(map[string]bool)//找到最便宜节点,得到开销值                               smallestCost,smallestName := findSmallestCost(cost,handled)for smallestCost < 1000{//找到邻居节点neighbor := graph[smallestName]//遍历邻居节点for i,v := range neighbor{if _, ok := cost[i]; ok {newCost := v + cost[smallestName]//得到邻居新的开销//如果小于之前的开销,更新开销,并更新parent节点信息if(newCost<cost[i]){cost[i] = newCostparent[i] = smallestName}}else{cost[i]=v+cost[smallestName]parent[i] = smallestName}}//将该节点加入到handled中handled[smallestName]=truesmallestCost,smallestName = findSmallestCost(cost,handled)//继续遍历其他节点}fmt.Printf("%+v\n",parent)
}func findSmallestCost(cost map[string]int,handled map[string]bool) (a int,b string){smallest := 1000target :=""for i,v := range cost{if _,ok := handled[i];!ok{if(v<smallest){smallest = vtarget=i}}}return smallest,target
}
复制代码

贪心算法——Dijkstra相关推荐

  1. 贪心算法——Dijkstra最短路径

    14天阅读挑战赛 目录 1.问题描述 2.问题分析 3.算法设计 4.C++程序 5.算法分析 1.问题描述 对于有向带权图G=(V,E),其中每条边的权值都是非负实数.给定V中的一个节点(称为源点) ...

  2. 贪心算法单源点最短路径例题c语言源代码,Dijkstra算法是解单源最短路径问题的一个贪心算法...

    问题描述 给定一个带权有向图 G=(V,E) ,其中每条边的权是一个非负实数. 另外,还给定 V 中的一个项点,称为源. 现在我们要计算从源到所有其他各项点的最短路径长度. 这里的长度是指路上各边权之 ...

  3. Dijkstra 贪心算法 动态规划

    我认为 Dijkstra算法 的本质是 广度优先搜索, 而此处的广度是定义在路程的cost之上的. (就好比从圆心处向外扩散一个圆环,首次碰到的就是最近) 动态规划泛指,重叠子问题与原问题的推算关系( ...

  4. 贪心算法之用优先队列解决最短路径问题(Dijkstra算法)

    1.问题 最短路径问题(Dijkstra算法)用 优先队列实现,问题描述和分析和优先队列先看前面我的几篇博客 贪心算法之最短路径问题(Dijkstra算法) C++之STL之priority_queu ...

  5. 【算法设计与分析】 单源最短路径(贪心算法) Dijkstra

    [算法设计与分析] 单源最短路径(贪心算法) Dijkstra [问题描述] Dijkstra算法解决的是带权重的有向图上单源最短路径问题.所有边的权重都为非负值.设置顶点集合S并不断地作贪心选择来扩 ...

  6. 常用十大算法 非递归二分查找、分治法、动态规划、贪心算法、回溯算法(骑士周游为例)、KMP、最小生成树算法:Prim、Kruskal、最短路径算法:Dijkstra、Floyd。

    十大算法 学完数据结构该学什么?当然是来巩固算法,下面介绍了十中比较常用的算法,希望能帮到大家. 包括:非递归二分查找.分治法.动态规划.贪心算法.回溯算法(骑士周游为例).KMP.最小生成树算法:P ...

  7. 贪心算法、DijKstra算法

    算法设计思想     1.贪心.贪婪算法     2.分而治之 → 快排 + 拓展的归并     3.动态规划     4.回溯        → 递归  n皇后问题     5.分支定界 基本思想 ...

  8. 11.贪心算法入门-----Dijkstra算法详解

    Dijkstra算法详细(单源最短路径算法) 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算 ...

  9. 算法设计与分析第3章 贪心算法

    第4章 贪心算法 贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 贪心算法的基本要素 1.贪心选择性质 所谓贪心选择性质是指所 ...

最新文章

  1. springboot整合websocket实现群聊
  2. 原型模式coding-克隆破坏单例
  3. C++ Prime:sizeof运算符
  4. mysql 正则替换 换行,MySQL中使用replace、regexp进行正则表达式替换的用法分析
  5. 苹果CMSV10橙色自适应25影视网主题模板
  6. 用Dart搭建HTTP服务器(3)
  7. C++中缀表达式求值(中缀表达式转后缀表达式)
  8. php整数和浮点数比较,php 浮点数怎么进行比较?
  9. 客流分析江湖争端再起,新旧势力谁更胜一筹?
  10. 彻底卸载VS2015
  11. 基于 Flink、ClickHouse 的舆情分析系统:系统详细设计说明书
  12. 2017onsite比赛游记帖
  13. 从键盘读入3个字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件1.txt中保存
  14. 面试题之细胞分裂问题
  15. SQL基础系列(七)——CASE表达式
  16. CSS层叠样式表基础知识整理
  17. 微信小程序 API的 promise化
  18. 【前端系列教程之CSS3】04_CSS定位和浮动详解
  19. XENIRO 讯琥科技应用案例(八)| 基于边缘计算和区块链的跨境漫游结算
  20. 通过编程语言窥视UBTC(比特联储)智能合约

热门文章

  1. linux 用户磁盘限额quota
  2. 当年入门时写的的《大富翁》
  3. 电信直连、CN2(GIA)本土运营商
  4. Office 2003 2007兼容器,使office 2003 2007一起工作
  5. 职称计算机word2003最新题库,职称计算机-Word2003操作题库
  6. java基于springboot社区养老服务管理系统附源码
  7. AI Vision全球开发者项目合作计划产品发布会顺利举办,物联网人工智能机器视觉行业代表参会
  8. redis缓存雪崩、缓存击穿和缓存穿透还傻傻分不清?看这篇就够了
  9. 计算机第三章ppt课件,计算机英语第三章课件.ppt
  10. vue2 几种初始化 挂载方式