-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUF.java
More file actions
174 lines (164 loc) · 6.74 KB
/
Copy pathUF.java
File metadata and controls
174 lines (164 loc) · 6.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/****************************************************************************
* Compilation: javac UF.java
* Execution: java UF < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: http://algs4.cs.princeton.edu/15uf/tinyUF.txt
* http://algs4.cs.princeton.edu/15uf/mediumUF.txt
* http://algs4.cs.princeton.edu/15uf/largeUF.txt
*
* Weighted quick-union by rank with path compression by halving.
*
* % java UF < tinyUF.txt
* 4 3
* 3 8
* 6 5
* 9 4
* 2 1
* 5 0
* 7 2
* 6 1
* 2 components
*
****************************************************************************/
/**
* The <tt>UF</tt> class represents a <em>union-find data type</em>
* (also known as the <em>disjoint-sets data type</em>).
* It supports the <em>union</em> and <em>find</em> operations,
* along with a <em>connected</em> operation for determinig whether
* two sites in the same component and a <em>count</em> operation that
* returns the total number of components.
* <p>
* The union-find data type models connectivity among a set of <em>N</em>
* sites, named 0 through <em>N</em> – 1.
* The <em>is-connected-to</em> relation must be an
* <em>equivalence relation</em>:
* <ul>
* <p><li> <em>Reflexive</em>: <em>p</em> is connected to <em>p</em>.
* <p><li> <em>Symmetric</em>: If <em>p</em> is connected to <em>q</em>,
* <em>q</em> is connected to <em>p</em>.
* <p><li> <em>Transitive</em>: If <em>p</em> is connected to <em>q</em>
* and <em>q</em> is connected to <em>r</em>, then
* <em>p</em> is connected to <em>r</em>.
* </ul>
* An equivalence relation partitions the sites into
* <em>equivalence classes</em> (or <em>components</em>). In this case,
* two sites are in the same component if and only if they are connected.
* Both sites and components are identified with integers between 0 and
* <em>N</em> – 1.
* Initially, there are <em>N</em> components, with each site in its
* own component. The <em>component identifier</em> of a component
* (also known as the <em>root</em>, <em>canonical element</em>, <em>leader</em>,
* or <em>set representative</em>) is one of the sites in the component:
* two sites have the same component identifier if and only if they are
* in the same component.
* <ul>
* <p><li><em>union</em>(<em>p</em>, <em>q</em>) adds a
* connection between the two sites <em>p</em> and <em>q</em>.
* If <em>p</em> and <em>q</em> are in different components,
* then it replaces
* these two components with a new component that is the union of
* the two.
* <p><li><em>find</em>(<em>p</em>) returns the component
* identifier of the component containing <em>p</em>.
* <p><li><em>connected</em>(<em>p</em>, <em>q</em>)
* returns true if both <em>p</em> and <em>q</em>
* are in the same component, and false otherwise.
* <p><li><em>count</em>() returns the number of components.
* </ul>
* The component identifier of a component can change
* only when the component itself changes during a call to
* <em>union</em>—it cannot change during a call
* to <em>find</em>, <em>connected</em>, or <em>count</em>.
* <p>
* This implementation uses weighted quick union by rank with path compression
* by halving.
* Initializing a data structure with <em>N</em> sites takes linear time.
* Afterwards, the <em>union</em>, <em>find</em>, and <em>connected</em>
* operations take logarithmic time (in the worst case) and the
* <em>count</em> operation takes constant time.
* Moreover, the amortized time per <em>union</em>, <em>find</em>,
* and <em>connected</em> operation has inverse Ackermann complexity.
* For alternate implementations of the same API, see
* {@link QuickUnionUF}, {@link QuickFindUF}, and {@link WeightedQuickUnionUF}.
*
* <p>
* For additional documentation, see <a href="http://algs4.cs.princeton.edu/15uf">Section 1.5</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class UF {
private int[] id; // id[i] = parent of i
private byte[] rank; // rank[i] = rank of subtree rooted at i (cannot be more than 31)
private int count; // number of components
/**
* Initializes an empty union-find data structure with <tt>N</tt>
* isolated components <tt>0</tt> through <tt>N-1</tt>
* @throws java.lang.IllegalArgumentException if <tt>N < 0</tt>
* @param N the number of sites
*/
public UF(int N) {
if (N < 0) throw new IllegalArgumentException();
count = N;
id = new int[N];
rank = new byte[N];
for (int i = 0; i < N; i++) {
id[i] = i;
rank[i] = 0;
}
}
/**
* Returns the component identifier for the component containing site <tt>p</tt>.
* @param p the integer representing one object
* @return the component identifier for the component containing site <tt>p</tt>
* @throws java.lang.IndexOutOfBoundsException unless <tt>0 ≤ p < N</tt>
*/
public int find(int p) {
if (p < 0 || p >= id.length) throw new IndexOutOfBoundsException();
while (p != id[p]) {
id[p] = id[id[p]]; // path compression by halving
p = id[p];
}
return p;
}
/**
* Returns the number of components.
* @return the number of components (between <tt>1</tt> and <tt>N</tt>)
*/
public int count() {
return count;
}
/**
* Are the two sites <tt>p</tt> and <tt>q</tt> in the same component?
* @param p the integer representing one site
* @param q the integer representing the other site
* @return true if the two sites <tt>p</tt> and <tt>q</tt> are in the same component; false otherwise
* @throws java.lang.IndexOutOfBoundsException unless
* both <tt>0 ≤ p < N</tt> and <tt>0 ≤ q < N</tt>
*/
public boolean connected(int p, int q) {
return find(p) == find(q);
}
/**
* Merges the component containing site <tt>p</tt> with the
* the component containing site <tt>q</tt>.
* @param p the integer representing one site
* @param q the integer representing the other site
* @throws java.lang.IndexOutOfBoundsException unless
* both <tt>0 ≤ p < N</tt> and <tt>0 ≤ q < N</tt>
*/
public void union(int p, int q) {
int i = find(p);
int j = find(q);
if (i == j) return;
// make root of smaller rank point to root of larger rank
if (rank[i] < rank[j]) id[i] = j;
else if (rank[i] > rank[j]) id[j] = i;
else {
id[j] = i;
rank[i]++;
}
count--;
}
}