Skip to content

Commit 38517bc

Browse files
committed
add java code to compare different path compression implementation in UF.
1 parent 92ac953 commit 38517bc

File tree

4 files changed

+100
-11
lines changed

4 files changed

+100
-11
lines changed

06-Union-Find/Course Code (Java)/Optional-01-Same-Cases-Test-for-UF/src/bobo/algo/Main.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
public class Main {
44

5-
// 对比UF1, UF2, UF3, UF4和UF5的时间性能
5+
// 对比UF1, UF2, UF3, UF4, UF5和UF6的时间性能
66
// 在这里, 我们对于不同的UnionFind的实现, 使用相同的测试用例, 让测试结果更加准确
77
public static void main(String[] args) {
88

9-
// 使用1000000的数据规模
10-
int n = 1000000;
9+
// 使用5000000的数据规模
10+
int n = 5000000;
1111

1212
// 生成unionElements的测试用例
1313
Pair<Integer, Integer>[] unionTest = new Pair[n];
@@ -25,7 +25,7 @@ public static void main(String[] args) {
2525
connectTest[i] = new Pair<Integer, Integer>(a, b);
2626
}
2727

28-
// 测试我们的UF1 ~ UF5
28+
// 测试我们的UF1 ~ UF6
2929

3030
// 100万数据对于UF1和UF2来说太慢了, 不再测试
3131
// UnionFind1 uf1 = new UnionFind1(n);
@@ -42,5 +42,8 @@ public static void main(String[] args) {
4242

4343
UnionFind5 uf5 = new UnionFind5(n);
4444
UnionFindTestHelper.testUF("UF5", uf5, unionTest, connectTest);
45+
46+
UnionFind6 uf6 = new UnionFind6(n);
47+
UnionFindTestHelper.testUF("UF6", uf6, unionTest, connectTest);
4548
}
4649
}

06-Union-Find/Course Code (Java)/Optional-01-Same-Cases-Test-for-UF/src/bobo/algo/UnionFind5.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package bobo.algo;
22

3-
// 我们的第五版Union-Find
3+
// 我们的第五版Union-Find, 路径压缩使用迭代实现
44
public class UnionFind5 implements UF {
55

66
// rank[i]表示以i为根的集合所表示的树的层数
@@ -34,11 +34,6 @@ private int find(int p){
3434
p = parent[p];
3535
}
3636
return p;
37-
38-
// path compression 2, 递归算法
39-
// if( p != parent[p] )
40-
// parent[p] = find( parent[p] );
41-
// return parent[p];
4237
}
4338

4439
// 查看元素p和元素q是否所属一个集合
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package bobo.algo;
2+
3+
// 我们的第六版Union-Find, 路径压缩使用递归实现
4+
public class UnionFind6 implements UF {
5+
6+
// rank[i]表示以i为根的集合所表示的树的层数
7+
// 在后续的代码中, 我们并不会维护rank的语意, 也就是rank的值在路径压缩的过程中, 有可能不在是树的层数值
8+
// 这也是我们的rank不叫height或者depth的原因, 他只是作为比较的一个标准
9+
// 关于这个问题,可以参考问答区:http://coding.imooc.com/learn/questiondetail/7287.html
10+
private int[] rank;
11+
private int[] parent; // parent[i]表示第i个元素所指向的父节点
12+
private int count; // 数据个数
13+
14+
// 构造函数
15+
public UnionFind6(int count){
16+
rank = new int[count];
17+
parent = new int[count];
18+
this.count = count;
19+
// 初始化, 每一个parent[i]指向自己, 表示每一个元素自己自成一个集合
20+
for( int i = 0 ; i < count ; i ++ ){
21+
parent[i] = i;
22+
rank[i] = 1;
23+
}
24+
}
25+
26+
// 查找过程, 查找元素p所对应的集合编号
27+
// O(h)复杂度, h为树的高度
28+
private int find(int p){
29+
assert( p >= 0 && p < count );
30+
31+
// path compression 2, 递归算法
32+
if( p != parent[p] )
33+
parent[p] = find( parent[p] );
34+
return parent[p];
35+
}
36+
37+
// 查看元素p和元素q是否所属一个集合
38+
// O(h)复杂度, h为树的高度
39+
public boolean isConnected( int p , int q ){
40+
return find(p) == find(q);
41+
}
42+
43+
// 合并元素p和元素q所属的集合
44+
// O(h)复杂度, h为树的高度
45+
public void unionElements(int p, int q){
46+
47+
int pRoot = find(p);
48+
int qRoot = find(q);
49+
50+
if( pRoot == qRoot )
51+
return;
52+
53+
// 根据两个元素所在树的元素个数不同判断合并方向
54+
// 将元素个数少的集合合并到元素个数多的集合上
55+
if( rank[pRoot] < rank[qRoot] ){
56+
parent[pRoot] = qRoot;
57+
}
58+
else if( rank[qRoot] < rank[pRoot]){
59+
parent[qRoot] = pRoot;
60+
}
61+
else{ // rank[pRoot] == rank[qRoot]
62+
parent[pRoot] = qRoot;
63+
rank[qRoot] += 1; // 此时, 我维护rank的值
64+
}
65+
}
66+
}

06-Union-Find/Course Code (Java)/Optional-01-Same-Cases-Test-for-UF/src/bobo/algo/UnionFindTestHelper.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,32 @@ public static void testUF5( int n ){
130130
long endTime = System.currentTimeMillis();
131131

132132
// 打印输出对这2n个操作的耗时
133-
System.out.println("UF4, " + 2*n + " ops, " + (endTime-startTime) + "ms");
133+
System.out.println("UF5, " + 2*n + " ops, " + (endTime-startTime) + "ms");
134+
}
135+
136+
// 测试第六版本的并查集, 测试元素个数为n, 测试逻辑和之前是完全一样的
137+
public static void testUF6( int n ){
138+
139+
UnionFind6 uf = new UnionFind6(n);
140+
141+
long startTime = System.currentTimeMillis();
142+
143+
// 进行n次操作, 每次随机选择两个元素进行合并操作
144+
for( int i = 0 ; i < n ; i ++ ){
145+
int a = (int)(Math.random()*n);
146+
int b = (int)(Math.random()*n);
147+
uf.unionElements(a,b);
148+
}
149+
// 再进行n次操作, 每次随机选择两个元素, 查询他们是否同属一个集合
150+
for(int i = 0 ; i < n ; i ++ ){
151+
int a = (int)(Math.random()*n);
152+
int b = (int)(Math.random()*n);
153+
uf.isConnected(a,b);
154+
}
155+
long endTime = System.currentTimeMillis();
156+
157+
// 打印输出对这2n个操作的耗时
158+
System.out.println("UF6, " + 2*n + " ops, " + (endTime-startTime) + "ms");
134159
}
135160

136161
// 使用相同的测试数据测试UF的执行效率

0 commit comments

Comments
 (0)