1.Quick-find
Quick-find
import java.io.*;
import java.net.*;
//并查集
public class Temp {
public static void main(String[] args){
Quick_find a = new Quick_find(5);
a.union(1,2);
a.union(3,2);
System.out.println(a.connected(1,2));
System.out.println(a.connected(3,4));
System.out.println(a.connected(1,3));
}
}
class Quick_find {
int id[];
Quick_find(int N){
id = new int[N];
for(int i = 0;i<N;++i){ //初始化id
id[i] = i;
}
}
boolean connected(int p,int q){ //id是否相同,相同则连通
return id[p]==id[q];
}
void union(int p ,int q) { //将相关连通id更新
int j = id[q];
for(int i = 0;i<id.length;++i){
if(id[i]==id[p])
id[i] = j;
}
}
}
/*分析复杂度
* Initialize:O(N)
* Find:O(1)
* Union:O(N)
* */
2.Quick-union
Quick-union
//id存储其“父结点”
class Quick_UnionUF {
private int id[];
Quick_UnionUF(int N) {
id = new int[N]; //id初始化
for (int i = 0; i < N; ++i)
id[i] = i;
}
int root(int i) { //get 根
while (i != id[i])
i = id[i];
return i;
}
boolean connected(int p, int q) { //根节点是否相同
return root(p) == root(q);
}
void union(int p, int q) { //根节点union
int i = root(p);
int j = root(q);
if (i != j) id[i] = j; //实际上根节点 j = id[j]
}
}
/*复杂度分析
Initialize:O(N)
Find: O(N) -worst
Union:O(N*) -include time of finding obj 最坏即每次union都是N 出现tall tree,在某些时候快,因为只需要操作一个结点,但是查找可能会较长时间
*/
3.Weighted-QU
Weighted+QU
class WeightedQU { //加权快速合并--小树并大树
private int id[];
private int sz[]; //表根所在树的obj个数
WeightedQU(int N) {
id = new int[N];
sz = new int[N];
for (int i = 0; i < N; ++i) {
id[i] = i;
sz[i] = 1; //每个所在树结点为1
}
}
int root(int i) { //get 根
while (i != id[i])
i = id[i];
return i;
}
boolean connected(int p, int q) { //same of QU,判断根结点是否同
return root(p) == root(q);
}
void union(int p, int q) {
int i = root(p);
int j = root(q);
if (sz[i] == sz[j]) {
id[i] = j; //小树根合并
sz[j] += sz[i];
}
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
} else {
id[j] = i;
sz[i] += sz[j];
}
}
}
/*复杂度分析
Initialize:O(N)
Find:lgN
Union:lgN* -include time of finding obj
简述:只有当一棵树>另一棵树的size时,depths会增加,所以没增加一层就会倍增size,n^k = N ==> depths = k = lgN ;
*/
4.Pathcopression-WeightedQU
Path compression+Weighted+QU
class Path_compression_WeightedQU{ //路径压缩+加权+快速合并
private int id[];
private int sz[]; //表根所在树的obj个数
Path_compression_WeightedQU(int N) {
id = new int[N];
sz = new int[N];
for (int i = 0; i < N; ++i) {
id[i] = i;
sz[i] = 1; //每个所在树结点为1
}
}
int root(int i) { //get 根
while (i != id[i]) {
id[i] = id[id[i]]; //每次合并会调用root函数,则每一次合并将树"基本展平"-使之指向祖父结点
i = id[i];
}
return i;
}
boolean connected(int p, int q) { //same of QU,判断根结点是否同
return root(p) == root(q);
}
void union(int p, int q) {
int i = root(p);
int j = root(q);
if (sz[i] == sz[j]) {
id[i] = j; //小树根合并
sz[j] += sz[i];
}
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
} else {
id[j] = i;
sz[i] += sz[j];
}
}
}
/*复杂度分析
在最坏复杂度上边,压缩路径+加权+QU 之后复杂度接近线性 O(N+Mlg*N) ~ O(N + 5M)
可以认为lg*N<5 because of lg*2^65536 = 5;(即取5次lg即将2^65536变为1)
*/
/*小总结
经证明,在并查集的算法中不存在线性算法
algorithm & worst-case time
quick-find M*N
quick-union M*N
weighted+QU N+MlogN
path compression+QU N+MlogN
weighted+path+QU N+Mlg*N
*/