QuickFindUF.java
QuickFindUF.java
package
UnionFind_SourceCode
;
public
class
QuickFindUF
{
private
int
[]
id
;
// id[i] = component identifier of i
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
QuickFindUF
(
int
n
)
{
count
=
n
;
id
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
id
[
i
]
=
i
;
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
return
id
[
p
];
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
id
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
"index "
+
p
+
" is not between 0 and "
+
(
n
-
1
));
}
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
validate
(
p
);
validate
(
q
);
return
id
[
p
]
==
id
[
q
];
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
validate
(
p
);
validate
(
q
);
int
pID
=
id
[
p
];
// needed for correctness
int
qID
=
id
[
q
];
// to reduce the number of array accesses
// p and q are already in the same component
if
(
pID
==
qID
)
return
;
for
(
int
i
=
0
;
i
<
id
.
length
;
i
++
)
if
(
id
[
i
]
==
pID
)
id
[
i
]
=
qID
;
count
--
;
}
/**
* Reads an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
64
;
QuickFindUF
uf
=
new
QuickFindUF
(
n
);
for
(
int
k
=
0
;
k
<
n
-
1
;
k
++
)
uf
.
union
(
k
,
k
+
1
);
uf
.
displaySubsets
(
);
// Test 1(a)
uf
=
new
QuickFindUF
(
n
);
// equivalent to reset, old gets garbage collected
for
(
int
k
=
0
;
k
<
n
-
1
;
k
++
)
uf
.
union
(
k
,
n
-
1
);
uf
.
displaySubsets
(
);
// Test 1(b)
uf
=
new
QuickFindUF
(
n
);
// equivalent to reset, old gets garbage collected
for
(
int
k
=
0
;
k
<
n
-
1
;
k
+=
4
){
uf
.
union
(
k
,
k
+
1
);
uf
.
union
(
k
+
2
,
k
+
3
);
uf
.
union
(
k
,
k
+
3
);
}
for
(
int
k
=
0
;
k
<
n
-
1
;
k
+=
16
){
uf
.
union
(
k
,
k
+
4
);
uf
.
union
(
k
,
k
+
8
);
uf
.
union
(
k
,
k
+
12
);
}
uf
.
union
(
0
,
16
);
uf
.
union
(
0
,
32
);
uf
.
union
(
0
,
48
);
uf
.
displaySubsets
(
);
// Test 1(c)
}
// prints out the contents of the array id[] from id[0] to id[n-1]
private
void
displaySubsets
()
{
System
.
out
.
print
(
"["
);
for
(
int
i
=
0
;
i
<
id
.
length
;
i
++
)
{
System
.
out
.
print
(
id
[
i
]
+
" "
);
}
System
.
out
.
println
(
"]\n"
);
}
}
QuickUnionUF.java
QuickUnionUF.java
package
UnionFind_SourceCode
;
public
class
QuickUnionUF
{
private
int
[]
parent
;
// parent[i] = parent of i
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
QuickUnionUF
(
int
n
)
{
parent
=
new
int
[
n
];
count
=
n
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
parent
[
i
]
=
i
;
}
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
while
(
p
!=
parent
[
p
])
p
=
parent
[
p
];
return
p
;
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
parent
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
"index "
+
p
+
" is not between 0 and "
+
(
n
-
1
));
}
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
int
rootP
=
find
(
p
);
int
rootQ
=
find
(
q
);
if
(
rootP
==
rootQ
)
return
;
parent
[
rootP
]
=
rootQ
;
count
--
;
}
/**
* Reads an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
64
;
QuickUnionUF
uf
=
new
QuickUnionUF
(
n
);
for
(
int
k
=
0
;
k
<
n
-
1
;
k
++
)
uf
.
union
(
k
,
k
+
1
);
uf
.
displaySubsets
(
);
// Test 2(a)
uf
=
new
QuickUnionUF
(
n
);
// equivalent to reset...
for
(
int
k
=
0
;
k
<
n
-
1
;
k
++
)
uf
.
union
(
k
,
n
-
1
);
uf
.
displaySubsets
(
);
// Test 2(b)
uf
=
new
QuickUnionUF
(
n
);
// equivalent to reset...
for
(
int
k
=
0
;
k
<
n
-
1
;
k
+=
4
){
uf
.
union
(
k
,
k
+
1
);
uf
.
union
(
k
+
2
,
k
+
3
);
uf
.
union
(
k
,
k
+
3
);
}
for
(
int
k
=
0
;
k
<
n
-
1
;
k
+=
16
){
uf
.
union
(
k
,
k
+
4
);
uf
.
union
(
k
,
k
+
8
);
uf
.
union
(
k
,
k
+
12
);
}
uf
.
union
(
0
,
16
);
uf
.
union
(
0
,
32
);
uf
.
union
(
0
,
48
);
uf
.
displaySubsets
(
);
// Test 2(c)
}
// prints out the contents of the array id[] from id[0] to id[n-1]
private
void
displaySubsets
()
{
System
.
out
.
print
(
"["
);
for
(
int
i
=
0
;
i
<
parent
.
length
;
i
++
)
{
System
.
out
.
print
(
parent
[
i
]
+
" "
);
}
System
.
out
.
println
(
"]\n"
);
}
}
WeightedQuickUnionUF.java
WeightedQuickUnionUF.java
package
UnionFind_SourceCode
;
public
class
WeightedQuickUnionUF
{
private
int
[]
parent
;
// parent[i] = parent of i
private
int
[]
size
;
// size[i] = number of elements in subtree rooted at i
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
WeightedQuickUnionUF
(
int
n
)
{
count
=
n
;
parent
=
new
int
[
n
];
size
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
parent
[
i
]
=
i
;
size
[
i
]
=
1
;
}
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
while
(
p
!=
parent
[
p
])
p
=
parent
[
p
];
return
p
;
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
parent
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
"index "
+
p
+
" is not between 0 and "
+
(
n
-
1
));
}
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
int
rootP
=
find
(
p
);
int
rootQ
=
find
(
q
);
if
(
rootP
==
rootQ
)
return
;
// make smaller root point to larger one
if
(
size
[
rootP
]
<
size
[
rootQ
])
{
parent
[
rootP
]
=
rootQ
;
size
[
rootQ
]
+=
size
[
rootP
];
}
else
{
parent
[
rootQ
]
=
rootP
;
size
[
rootP
]
+=
size
[
rootQ
];
}
count
--
;
}
/**
* Reads an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
64
;
WeightedQuickUnionUF
uf
=
new
WeightedQuickUnionUF
(
n
);
for
(
int
k
=
0
;
k
<
n
-
1
;
k
++
)
uf
.
union
(
k
,
k
+
1
);
uf
.
displaySubsets
(
);
// Test 3(a)
uf
=
new
WeightedQuickUnionUF
(
n
);
// equivalent to reset...
for
(
int
k
=
0
;
k
<
n
-
1
;
k
++
)
uf
.
union
(
k
,
n
-
1
);
uf
.
displaySubsets
(
);
// Test 3(b)
uf
=
new
WeightedQuickUnionUF
(
n
);
// equivalent to reset...
for
(
int
k
=
0
;
k
<
n
-
1
;
k
+=
4
){
uf
.
union
(
k
,
k
+
1
);
uf
.
union
(
k
+
2
,
k
+
3
);
uf
.
union
(
k
,
k
+
3
);
}
for
(
int
k
=
0
;
k
<
n
-
1
;
k
+=
16
){
uf
.
union
(
k
,
k
+
4
);
uf
.
union
(
k
,
k
+
8
);
uf
.
union
(
k
,
k
+
12
);
}
uf
.
union
(
0
,
16
);
uf
.
union
(
0
,
32
);
uf
.
union
(
0
,
48
);
uf
.
displaySubsets
(
);
// Test 3(c)
}
// prints out the contents of the array id[] from id[0] to id[n-1]
private
void
displaySubsets
()
{
System
.
out
.
print
(
"["
);
for
(
int
i
=
0
;
i
<
parent
.
length
;
i
++
)
{
System
.
out
.
print
(
parent
[
i
]
+
" "
);
}
System
.
out
.
println
(
"]\n"
);
}
}