
数据结构源码 - UnionFind1
接口
public interface UnionFind {
int getSize();
boolean isConnected(int p, int q);
void unionElements(int p, int q);
}
实现类
public class UnionFind1 implements UnionFind {
private int[] id;
public UnionFind1(int size) {
id = new int[size];
for (int i = 0; i < id.length; i++) {
id[i] = i;
}
}
@Override
public int getSize() {
return id.length;
}
private int find(int p) {
if (p < 0 && p >= id.length)
throw new IllegalArgumentException("p is out of bound");
return id[p];
}
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
@Override
public void unionElements(int p, int q) {
int pID = find(p);
int qID = find(q);
if (pID == qID) {
return;
}
for (int i = 0; i < id.length; i++) {
if (id[i] == pID)
id[i] = qID;
}
}
}
数据结构拆解 - UnionFind1
维护字段和内部类
private int[] id;
构造函数
public UnionFind1(int size) {
id = new int[size];
for (int i = 0; i < id.length; i++) {
id[i] = i;
}
}
改
/**
* 合并元素p和q所属的集合
* @param p
* @param q
*/
@Override
public void unionElements(int p, int q) {
int pID = find(p)
int qID = find(q)
if (pID == qID) {
return
}
for (int i = 0
if (id[i] == pID)
id[i] = qID
}
}
查
@Override
public int getSize() {
return id.length;
}
private int find(int p) {
if (p < 0 && p >= id.length)
throw new IllegalArgumentException("p is out of bound");
return id[p];
}
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
数据结构源码 - UnionFind2
接口
public interface UnionFind {
int getSize();
boolean isConnected(int p, int q);
void unionElements(int p, int q);
}
实现类
import java.util.Random
/**
* 第二种UnionFind实现
*/
public class UnionFind2 implements UnionFind {
private int[] parent
public UnionFind2(int size) {
parent = new int[size]
for (int i = 0
parent[i] = i
}
}
@Override
public int getSize() {
return parent.length
}
/**
* 查找过程,查找元素p所对应的集合编号
* O(h)复杂度,h为树高度
* @param p
* @return
*/
private int find(int p) {
if (p < 0 && p >= parent.length)
throw new IllegalArgumentException("p is out of bound")
while (p != parent[p]) {
p = parent[p]
}
return p
}
/**
* 查看元素p和元素q是否所属一个集合
* @param p
* @param q
* @return
*/
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q)
}
/**
* 合并元素p和元素q所属的集合
* O(h)复杂度,h为树的高度
* @param p
* @param q
*/
@Override
public void unionElements(int p, int q) {
int pRoot = find(p)
int qRoot = find(q)
if (pRoot == qRoot)
return
parent[pRoot] = qRoot
}
private static double testUF(UnionFind uf, int m) {
int size = uf.getSize()
Random random = new Random()
long startTime = System.nanoTime()
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.unionElements(a, b)
}
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.isConnected(a, b)
}
long endTime = System.nanoTime()
return (endTime - startTime) / 1000000000.0
}
public static void main(String[] args) {
int size = 100000
int m = 100000
UnionFind1 uf1 = new UnionFind1(size)
System.out.println("UnionFind1 : " + testUF(uf1, m) + " s")
UnionFind2 uf2 = new UnionFind2(size)
System.out.println("UnionFind2 : " + testUF(uf2, m) + " s")
}
}
数据结构拆解 - UnionFind2
维护字段和内部类
private int[] parent;
构造函数
public UnionFind2(int size) {
parent = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;
}
}
改
/**
* 合并元素p和元素q所属的集合
* O(h)复杂度,h为树的高度
* @param p
* @param q
*/
@Override
public void unionElements(int p, int q) {
int pRoot = find(p)
int qRoot = find(q)
if (pRoot == qRoot)
return
parent[pRoot] = qRoot
}
查
@Override
public int getSize() {
return parent.length;
}
private int find(int p) {
if (p < 0 && p >= parent.length)
throw new IllegalArgumentException("p is out of bound");
while (p != parent[p]) {
p = parent[p];
}
return p;
}
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
测试用例 - UnionFind2
private static double testUF(UnionFind uf, int m) {
int size = uf.getSize()
Random random = new Random()
long startTime = System.nanoTime()
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.unionElements(a, b)
}
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.isConnected(a, b)
}
long endTime = System.nanoTime()
return (endTime - startTime) / 1000000000.0
}
public static void main(String[] args) {
int size = 100000
int m = 100000
UnionFind1 uf1 = new UnionFind1(size)
System.out.println("UnionFind1 : " + testUF(uf1, m) + " s")
UnionFind2 uf2 = new UnionFind2(size)
System.out.println("UnionFind2 : " + testUF(uf2, m) + " s")
}
数据结构源码 - UnionFind3
接口
public interface UnionFind {
int getSize();
boolean isConnected(int p, int q);
void unionElements(int p, int q);
}
实现类
import java.util.Random
/**
* 第二种UnionFind实现
*/
public class UnionFind3 implements UnionFind {
private int[] parent
private int[] sz
public UnionFind3(int size) {
parent = new int[size]
sz = new int[size]
for (int i = 0
parent[i] = i
sz[i] = 1
}
}
@Override
public int getSize() {
return parent.length
}
/**
* 查找过程,查找元素p所对应的集合编号
* O(h)复杂度,h为树高度
* @param p
* @return
*/
private int find(int p) {
if (p < 0 && p >= parent.length)
throw new IllegalArgumentException("p is out of bound")
while (p != parent[p]) {
p = parent[p]
}
return p
}
/**
* 查看元素p和元素q是否所属一个集合
* @param p
* @param q
* @return
*/
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q)
}
/**
* 合并元素p和元素q所属的集合
* O(h)复杂度,h为树的高度
* @param p
* @param q
*/
@Override
public void unionElements(int p, int q) {
int pRoot = find(p)
int qRoot = find(q)
if (pRoot == qRoot)
return
// 根据两个元素所在树的元素个数不同判断合并方向
if (sz[pRoot] < sz[qRoot]) {
parent[pRoot] = qRoot
sz[qRoot] += sz[pRoot]
}
else { // sz[qRoot] <= sz[pRoot]
parent[qRoot] = pRoot
sz[pRoot] += sz[qRoot]
}
}
private static double testUF(UnionFind uf, int m) {
int size = uf.getSize()
Random random = new Random()
long startTime = System.nanoTime()
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.unionElements(a, b)
}
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.isConnected(a, b)
}
long endTime = System.nanoTime()
return (endTime - startTime) / 1000000000.0
}
public static void main(String[] args) {
int size = 100000
int m = 100000
UnionFind1 uf1 = new UnionFind1(size)
System.out.println("UnionFind1 : " + testUF(uf1, m) + " s")
UnionFind2 uf2 = new UnionFind2(size)
System.out.println("UnionFind2 : " + testUF(uf2, m) + " s")
UnionFind3 uf3 = new UnionFind3(size)
System.out.println("UnionFind3 : " + testUF(uf3, m) + " s")
}
}
数据结构拆解 - UnionFind3
维护字段和内部类
private int[] parent;
private int[] sz;
构造函数
public UnionFind3(int size) {
parent = new int[size]
sz = new int[size]
for (int i = 0
parent[i] = i
sz[i] = 1
}
}
改
/**
* 合并元素p和元素q所属的集合
* O(h)复杂度,h为树的高度
* @param p
* @param q
*/
@Override
public void unionElements(int p, int q) {
int pRoot = find(p)
int qRoot = find(q)
if (pRoot == qRoot)
return
// 根据两个元素所在树的元素个数不同判断合并方向
if (sz[pRoot] < sz[qRoot]) {
parent[pRoot] = qRoot
sz[qRoot] += sz[pRoot]
}
else { // sz[qRoot] <= sz[pRoot]
parent[qRoot] = pRoot
sz[pRoot] += sz[qRoot]
}
}
查
@Override
public int getSize() {
return parent.length;
}
private int find(int p) {
if (p < 0 && p >= parent.length)
throw new IllegalArgumentException("p is out of bound");
while (p != parent[p]) {
p = parent[p];
}
return p;
}
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
测试用例 - UnionFind3
private static double testUF(UnionFind uf, int m) {
int size = uf.getSize()
Random random = new Random()
long startTime = System.nanoTime()
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.unionElements(a, b)
}
for (int i = 0
int a = random.nextInt(size)
int b = random.nextInt(size)
uf.isConnected(a, b)
}
long endTime = System.nanoTime()
return (endTime - startTime) / 1000000000.0
}
public static void main(String[] args) {
int size = 100000
int m = 100000
UnionFind1 uf1 = new UnionFind1(size)
System.out.println("UnionFind1 : " + testUF(uf1, m) + " s")
UnionFind2 uf2 = new UnionFind2(size)
System.out.println("UnionFind2 : " + testUF(uf2, m) + " s")
UnionFind3 uf3 = new UnionFind3(size)
System.out.println("UnionFind3 : " + testUF(uf3, m) + " s")
}