算法学习之union-find
2016年12月16日最近开始在跟进coursera的算法课程,为明年的实习面试做准备。Sedgewick的这门算法课程非常出名,配套的有一本书叫做《Algorithms》,和Coursera上的课程配套。
第一周课程先以一个案例即union-find算法为例,阐述算法分析的基础。
##动态连通性
union-find算法要解决的是一个连通性问题。首先,问题描述:
给定一个有N个对象的集合,定义如下操作:
- Union command: 连接两个对象。
- Find/connected query:两个对象之间是否是连通的。
该问题有许多应用场景,如迷宫寻路,物理化学中的渗流和通信网络中的连通性等等。
算法的API定义:1
2
3
4
5
6public class UF
UF(int N) inial union-find data stucture with N objects(0 to N-1)
void union(int p, int q) add connection between p and q
boolean connected(int p, int q) are p and q in the same component?
int find(int p) component identifier for p(0 to N-1)
int count() number of component
动态连通性client1
2
3
4
5
6
7
8
9
10
11
12publci static void main(String[] args) {
int N = StdIn.readInt();
UF uf = new UF(N);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (!uf.connected(p, q)) {
uf.union(p, q);
StdOut.println(p + " " + q);
}
}
}
输出实例:
课程实现了两种UnionFind算法,逐渐优化。
Quick-find
第一种使用暴力方法,每次union(p, q),将所有值为q的索引的值更新为q
1 | public class QuickFindUF { |
Quick-uinion
使用数据结构“树”,同一子集有相同的祖先节点(根节点)。
1 | public class QuickUnionUF { |
改进一:加权
防止“树枝”过长,根据权重调节树枝长度。
修改union
:1
2
3
4
5
6
7
8
9
10int i = root(p);
int j = root(q);
if (i == j) return;
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
} else {
id[j] = i;
sz[i] += sz[j];
}
改进二:路径压缩
1 | private int root(int i) { |
课程作业——渗透问题(Pecolation)
问题描述的网址在Programming Assignment 1: Pecolation
寒假有空整理下,未完待续……