Featured image of post CS61B week9 学习笔记

CS61B week9 学习笔记

包括第九周讲座内容

lec23 Shortest Paths

引入

BFS 只会考虑边的个数。如果每个边有不同的长度,那么就不能简单地使用 BFS。

显然,最佳的路径不会有圈。

lec23-1.png 很有趣的是,最后各个节点的最优路径会形成一棵树。包括有向图和无向图。这个路径成为 Shortest Path Tree(SPT)。

在 SPT 中,边的个数总数 V-1,V 为节点的个数。

尝试

第一个算法

一开始所有节点的距离设置为无穷。然后进行深度优先搜索,对于相邻每个节点,如果不在 SPT 中,就加入这个边。然而,这样无法得到最短的路径,因为只要有节点被标记,就不再遍历相应的边。

第二个算法

利用深度优先搜索,如果某个边可以产生更短的距离,就将这个边加入 SPT。在这个例子中,考虑 C 之后应该重新考虑 B,才有可能得到最短路径。 lec23-2.png

Dijkstra

不要用深度优先,而是用"best first search"。

在每一次选择下一个遍历的节点时,聚焦于距离最短的那个节点。然后,计算各个边带来的距离,并且更新最短距离。 lec23-3.png

将所有的点插入 fringe PQ,储存节点距离源的距离。重复以下步骤:

  • 从 PQ 中移除距离最小的节点
  • 更新该节点指向的所有边,包括 distToedgeTo

lec24 Minimum Spanning Trees

引入

如何判断一个图当中是否有圈?

一:使用 DFS。从某个节点开始,直到遇到标记过的节点,但是不包括刚刚来的节点。最差情况是 $\Theta(V+E)$

二:使用并查集。对于每条边,检查两个节点是否相连。如果没有,就连接。如果有,就代表有环。最差情况为 $O(V+E\log*(V))$

最小生成树

只在无向图中存在。生成树是图的一个子集,包含所有节点,并且是连接、无环的。最小生成树意味着每条边的值加起来最小,即 MST。 lec24-1.png

在有些图中,从某些节点出发的 SPT 并不是 MST,但有些节点是。但有些图中,根本没有 SPT 是 MST。所以,不能通过先确定某个节点,再根据 Dijkstra 来找到 MST。

Cut 特性

Cut 将图中节点分类两类非空集合。一个交叉边就是连接两个不同集合节点的边。Cut 特性:给定任意的 Cut,拥有最小值的交叉边一定是 MST 的一部分。这可以通过反证法证明。 lec24-2.png

利用这个,可以找到一个 cut,它的交叉边都不在 MST 中,然后将最小值加入 MST。不断重复。

Prim 算法

第一次选取最短的边。然后考虑所有标记过的节点,将其和剩余节点看做一个 cut,然后找到最小值的边。当有两个相同最小值时,选择任意一个都行。有时候,MST 不是唯一的。

为了让 Prim 算法更高效,在 PQ 中储存节点距离树的距离。然后,找到最小的,将这个点从 fringe 中移除。 lec24-3.png

Dijkastra 考虑距离起点的距离,Prim 考虑距离树的距离。

在 E 大于 V 的情况下,时间复杂度为 $O(E\log(V))$。

Kruskal 算法

将所有边排序,从小的开始。如果加入后不导致成环,那就加入。与 Prim 不同,这个在过程中并不一定是互相连接的。

每次考虑最小边,将该节点在的一个树与剩余部分看成 Cut,根据性质,最小边在 MST 当中。

在实现中,为了判断成环,可以使用并查集。如果当前边对应节点在并查集中不相连,就连接两个节点;否则,说明成环,不能加入该边。为了追踪最小边,使用 PQ。

最终的消耗的时间主要取决于将所有边从 PQ 的加入、删除的时间,也就是 $O(E\log(E))$。不过,如果已经知道了图中各个边的大小次序,那么运行时间主要取决于并查集的速度,需要进行 E 次连接、是否连接的操作,总时间缩减到 $O(E\log*V)$。

lec25 Multidimentional data

多维数据引入

对于多维数据,不能简单地使用一个 BST 达到方便搜索的目的。例如对于有 x、y 坐标的对象,如果使用 x 坐标来构建二叉树,那么可以很方便地找到 x 坐标小于 1.5 的点。

通过剪枝,可以减少需要搜索的情况。 lec25-1.png

多叉树

四叉树

不像二叉树一样只有两个子节点,四叉树有四个节点,表示在二维空间中四种位置关系。和二叉树一样,不同的插入顺序会影响树的性能。

这时,要进行矩形的搜索更方便。如果矩形在某一点的四个区域之内,就可以对剩下的区域进行剪枝。

三维数据

类似地,可以使用八叉树。

然而,当维度更高的时候,使用这种思想就不太行,空间会呈指数型增长。

K-D 树

如果维度为 2,那么根节点根据 x 分类;深度为 1 的节点通过 y 分类;深度为 2 的节点通过 x 分类。以此类推。

有时候,如果发现数值相同,需要打破平衡,例如进入右子节点。

在寻找距离某个点最近的节点时,也可以使用 k-d 树方便地通过遍历,直到最近节点所在的区域。需要注意,还需要在之前没考虑的区域考虑。这种考虑也要靠近更好的区域。在之后考虑更差的区域时,判断该区域最优情况下的距离是否好于当前值。如果不是,可以剪枝。 lec25-2.png lec25-3.png lec25-4.png

均匀分割

将空间分成多个 buckets。在矩形搜索中,只用看在矩形之中的 buckets。不过,性能会比不上四叉树或 k-d 树。

均匀分割的思想和 hashing 比较像。

使用 Hugo 构建
主题 StackJimmy 设计