CS61BSpring2019笔记1: 图的最短路径以及最小生成树

CS61B Spring2019

开始写这个笔记的时候其实已经进行到课程的后半段了,之前的相关内容应该会在后续进行一个回顾和补充, 然后其实比起lecture本身,课程的labs、projects、hw更为重要一些。反正总的来说是一个项目基础+java语言+数据结构都有涉及且还是比较有深度的课程。

问题描述

ShortestPathTree

最短路径树规定了一个起点,到每个节点的树的分支路径要求是两个节点之间的最短路径,这样就形成了一个最短路径树。

MinimumSpanningTree

最小生成树相比于最短路径树并不固定起始节点,它要求生成的树路径权值(距离)之和最小。
在这里插入图片描述

简单比较

在这里插入图片描述

算法和实现

其实感觉实质上都是一种特殊规则的图遍历

最短路径树算法

Dijkstra

采用Dijkstra方法解决最短路径树问题,需要维护一个优先级队列distTo和一个记录路径的Array edgeTo[]。PQ中储存的是各个节点,优先级由更新后的到root(source vertex)的距离来定义。
初始化队列,建堆,其中只有root的优先级为0,其余皆为正无穷。
算法就是反复执行这么一系列操作,直到distTo为空。
(1)distTo弹出当前堆顶节点(距离root最近)
(2)遍历弹出结点的所有邻居,并更新它们的优先级(到root的距离),更新edgeTo[]。

在这里插入图片描述
具体流程见这个google文档: demo.
下面是伪代码
在这里插入图片描述
可以发现一个看似偶然但实则必然的现象,如果节点之前已经被弹出后,再次由于遍历后续节点被调用到,是一定不需要更新root到该节点的路径的,这也是该算法证明的一个关键。
简单证明如下:(前提是所有边的weight都非负)
在这里插入图片描述

A*

在实际应用当中我们往往不需要得出一整个树,更多只是希望可以最快的找到两个节点之间的最短路径,A*是一种在此类问题上更高效的启发式算法。
具体实现上,其实和dijkstra算法非常相似,只不过优先级队列的优先级不再只由当前节点到root(出发地)的距离去决定,而是引入了用于反映当前节点到最终目标节点(目的地)的估计参数h(v, goal) + 到出发地的距离。demo中采用了当前节点到邻居的最小值作为估计参数。
个人认为该算法的难点在于选择合理的arbitrary heuristic, 即如何设计h函数,在有效利用经验的同时,保证结果的收敛的正确性。
在这里插入图片描述

最小生成树算法

有了前面问题的基础,其实最小生成树算法在实现上的框架上是非常相似的,但是在理论上是完全不同的。

理论基础:Cut Property

大概的意思就是说如果把图的节点分为两组非空的节点set,那么这两组set之间连接的最短的边一定是MST中的树边。
证明也非常简单,由于MST一定是连通全图的,如果这条边是另一条较长边那么完全可以换成这条最短的边得到权值更小的MST,这与一开始的假设矛盾。
在这里插入图片描述

Prim

demo
在这里插入图片描述
可以看到算法结构与dijkstra是完全一模一样的,只不过PQ的优先级定义不同,在Prim中,当前节点的优先级定义为他到目前生成树的距离。最终由edgeTo Array还原路径。
在这里插入图片描述
Pseudocode
在这里插入图片描述
在这里插入图片描述
时间复杂度分析
PQ插入 + PQ删除 + 更改优先级
在这里插入图片描述

Kruskal

Prim在实现过程中算法时间复杂度还可以有进一步优化改进的空间。
Kruskal是一个非常简单的算法。
(1)把边按照权重的大小排序
(2)把边按照顺序加入MST中,直到会构成一个环(用查并集来做)
(3)重复操作直到MST中拥有V-1条边。
证明这里就不多说了,就是简单的Cut Property的应用。
在这里插入图片描述
Pseudocode
在这里插入图片描述
可以看到时间复杂度包括建堆算法(通过从下而上的下滤可以优化到O(E),这也是该算法时间复杂度提升的比较大的改进。
在这里插入图片描述

后续

之后可能会更新相关的leetcode题目。
因为时间有限,这个笔记确实写得还是非常的粗糙更多好像只是把自己的想法过了一变,之后经过比较熟练地应用之后可能会有更好的改进吧。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值