Princeton-Algorithm-Union Find

该文章为Princeton-Algorithms Part I读书笔记,相关视频在此。

1. 算法用于解决的问题: Dynamic Connectivity

1.1 两个操作:Union & Find

Union & Find

关键:ObjectS + Union + Find

1.2 Connected Component

Connected Components

2. 实现

2.1 Quick-Find

是一种eager approach,why?

  • 思想:利用一个id数组来对每个object进行分类


    quick find

Find(p, q): 查看各自的id是否相等
Union(p, q): 将所有与p的id相同的objects的id设置为与q的id相等

  • Java实现


    Java 实现
  • 效率:Union太慢。一次Union花O(N),连续对M个对象Union耗时O(MN)。

2.2 Quick-Union

是一种lazy approach

  • 思想:id数组中存着parent


    quick union

Find(p, q): 查看各自的root是否相等
Union(p, q): 将p的root的id设置为q的root的id

  • Java实现


    Java实现
  • 效率:Union还是太慢,可能花O(N)来find对象的root


    效率对比

可以从所维护的树的角度来考虑:
quick find: 树是平的,union之后改动很大
quick union: union虽然只需要对树一次改动,但是可能树很高,find花很长时间

3.优化

3.1 方法1: weighting

  • 思想

    • 对quick-union进行修改使之避免太高的树
    • 记录每个树包含的对象数 (size) Note:也可以是depth,算法complexity上是一样的,但是code不同
    • union操作时只将小的树的root连向大的树的root,这样尽量平衡了树,避免了树不断变高。
      unweighted vs weigthed
  • Java实现

java实现
  • 效率: 相当不错,每次union和find都是O(lgN)。连续对N个对象进行M次Union-Find操作耗时O(MlgN)。


    效率比较

为什么O(lgN)呢?因为一个节点最大深度只能为lgN
证明:
考虑一个节点x,什么时候深度才会递增1?当它所在的树小于要union的那棵树时。因此union之后,它所在的树的节点数翻倍。由于总节点数为N,因此x所在的树由节点数为1开始,最多能翻倍lgN次,即x的深度最多是lgN。

3.2 方法2:path compression

  • 思想:每次利用root(p)找到某个点的root时,再来一次循环将路径上的所有点都指向root,进而又减少了树的高度!

  • 效率:非常好。In theory, 连续对M个对象进行N次Union-Find操作的amortized的时间复杂度为O(MlgN)。In pratical, 其实甚至接近了线性耗时O(N).

    union find优化效率

4. 应用

4.1 Percolation穿透问题

percolation model

具有NXN的区域,每个单元格有一定的概率要么空,要么填充。问题是求解是否上边能穿透到下底。

更实际的应用有电路问题,流水问题,社交问题等

percolation application

此外,还有一个关于如何得到percolation threshold(穿透阈值)的实验:

estimate percolation threshold

技巧:引入上下两个virtual site便于check是否上边与下底相连

算法的发展思路
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容