代码和笔记整理
笔记简单整理
1.导入jar包的操作
2.设计类先抽象功能和需要用到的变量
3.先设计测试类的接口
4.一定要讨论数据结构和算法的应用场景
5.算法的时间复杂度需要自己跑跑试试,学会测试一切自己想测试的东西,不要迷信权威
并查集(Union-Find)
接口抽象
package unionFind;
import edu.princeton.cs.algs4.*;
public class UF {
//初始化
public UF(int n) {
// TODO 自动生成的构造函数存根
}
boolean connected(int p, int q) {
return false;
}
//合并
void union(int p ,int q) {}
public static void main(String[] args) {
//TODO 自动生成的方法存根
//输入规模
int N = StdIn.readInt();
//初始化
UF uf = new UF(N);
//初始化一些Union
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if(!uf.connected(p,q)) {
uf.union(p,q);
StdOut.println(p+" "+q);
}
}
//接下来可以判断任意两个值是否“相连”
}
}
QuickFind实现
package unionFind;
import edu.princeton.cs.algs4.*;
public class QuickFindUF {
//id标识着他们所在的集合
private int[] id;
//初始化
public QuickFindUF(int N){
id = new int[N];
for(int i = 0; i < N; i++) {
id[i] = i;
}
}
public boolean connected(int p, int q) {
return (id[p] == id[q]);
}
public void union(int p ,int q) {
int pid = id[p];
int qid = id[q];
for(int i = 0;i < id.length; i++) {
//union(q,p)指的是把所有跟p的id一样的点的id全部改为q的id
if(id[i] == pid) {
id[i] = qid;
}
}
}
}
时间复杂度:建立O(n),判断是否相连的connected操作为O(1),合并union操作为O(n)。
这里假设我们在用Quick-Find方法解决动态连通性问题时最终只得到了一个连通分量,那么我们在实际应用中至少要调用N-1次Union,所以显然它对于最终只能得到少数连通分量的一般应用是O(n2)级别的。
QuickUnion实现(加权、路径压缩)
package unionFind;
import edu.princeton.cs.algs4.*;
public class QuickUnionUF {
//每个节点的父节点
private int[] id;
private int[] sz;
public QuickUnionUF(int N){
sz = new int[N];
id = new int[N];
for(int i = 0; i < id.length; i++) {
id[i] = i;
}
}
private int root(int i) {
while(id[i] != i) {
//路径压缩!!简单的两次寻找可以让树的结构更好,深度大大减少的话,是非常划算的做法。
id[i] = id[id[i]];
i = id[i];
}
return i;
}
public boolean connected(int p, int q) {
return (root(p) == root(q));
}
public void union(int p ,int q) {
int proot = root(p);
int qroot = root(q);
if(proot == qroot) {
return;
}
//加权!,永远把小树加在大树上
if(sz[proot] < sz[qroot]) {
id[proot] = qroot;
sz[qroot] += sz[proot];
}else {
id[qroot] = proot;
sz[proot] += sz[qroot];
}
}
}
基础的Quick-Union只改良了QF算法的union操作,其union和connected操作的复杂度跟树高有关,但是最差情况下还是N级别,还不够,上文给出的是加权的QU算法(加权部分已注释),它一定有不超过log2n的树高,其union和connected操作都具有对数级别log2n的性能。路径压缩后效果更佳好。
遵循前面说的测试才是真理的想法,拿我的破电脑跑了一下1百万行的largeUF.txt(官网给的有 http://algs4.cs.princeton.edu/15uf/largeUF.txt ),还是挺慢的,吃饭期间挂着最后跑了15分钟跑出来了。不过如果用QF的方法,估计我自己这个破笔记本有生之间系列了。