Q. Is there a path connecting p and q ?
Quick-Union算法主要提供两个方法:
- Union:连接两个点
- Connected:判断两个点是否相连
- root(p) == root(q)则说明p与q相连
- root(p) != root(q)则说明p与q不相连
/****************************************************************************
* Compilation: javac QuickUnionUF.java
* Execution: java QuickUnionUF < input.txt
* Dependencies: StdIn.java StdOut.java
*
* Quick-union algorithm.
*
****************************************************************************/
/**
* The <tt>QuickUnionUF</tt> class represents a union-find data structure.
* It supports the <em>union</em> and <em>find</em> operations, along with
* methods for determinig whether two objects are in the same component
* and the total number of components.
* <p>
* This implementation uses quick union.
* Initializing a data structure with <em>N</em> objects takes linear time.
* Afterwards, <em>union</em>, <em>find</em>, and <em>connected</em> take
* time linear time (in the worst case) and <em>count</em> takes constant
* time.
* <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 QuickUnionUF {
private int[] id; // id[i] = parent of i
private int count; // number of components
/**
* Initializes an empty union-find data structure with N isolated components 0 through N-1.
* @throws java.lang.IllegalArgumentException if N < 0
* @param N the number of objects
*/
public QuickUnionUF(int N) {
id = new int[N];
count = N;
for (int i = 0; i < N; i++) {
id[i] = i;
}
}
/**
* Returns the number of components.
* @return the number of components (between 1 and N)
*/
public int count() {
return count;
}
/**
* Returns the component identifier for the component containing site <tt>p</tt>.
* @param p the integer representing one site
* @return the component identifier for the component containing site <tt>p</tt>
* @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N
*/
public int find(int p) {
while (p != id[p])
p = id[p];
return p;
}
/**
* 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 <tt>true</tt> if the sites <tt>p</tt> and <tt>q</tt> are in the same
* component, and <tt>false</tt> otherwise
* @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N
*/
public boolean connected(int p, int q) {
return find(p) == find(q);
}
/**
* Merges the component containing site<tt>p</tt> with 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 0 <= p < N and 0 <= q < N
*/
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ) return;
id[rootP] = rootQ;
count--;
}
/**
* Reads in a sequence of pairs of integers (between 0 and N-1) from standard input,
* where each integer represents some object;
* if the objects are in different components, merge the two components
* and print the pair to standard output.
*/
public static void main(String[] args) {
int N = StdIn.readInt();
QuickUnionUF uf = new QuickUnionUF(N);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.connected(p, q)) continue;
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
Quick-Union的缺点是:在极端情况下,树会生长成笔直的直线。可用Weighted Quick-Union算法改进。
if (sz[rootP] < sz[rootQ]) { id[rootP] = rootQ; sz[rootQ] += sz[rootP]; }
else { id[rootQ] = rootP; sz[rootP] += sz[rootQ]; }Weighted Quick-Union算法具体实现如下:
/****************************************************************************
* Compilation: javac WeightedQuickUnionUF.java
* Execution: java WeightedQuickUnionUF < input.txt
* Dependencies: StdIn.java StdOut.java
*
* Weighted quick-union (without path compression).
*
****************************************************************************/
/**
* The <tt>WeightedQuickUnionUF</tt> class represents a union-find data structure.
* It supports the <em>union</em> and <em>find</em> operations, along with
* methods for determinig whether two objects are in the same component
* and the total number of components.
* <p>
* This implementation uses weighted quick union by size (without path compression).
* Initializing a data structure with <em>N</em> objects takes linear time.
* Afterwards, <em>union</em>, <em>find</em>, and <em>connected</em> take
* logarithmic time (in the worst case) and <em>count</em> takes constant
* time.
* <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 WeightedQuickUnionUF {
private int[] id; // id[i] = parent of i
private int[] sz; // sz[i] = number of objects in subtree rooted at i
private int count; // number of components
/**
* Initializes an empty union-find data structure with N isolated components 0 through N-1.
* @throws java.lang.IllegalArgumentException if N < 0
* @param N the number of objects
*/
public WeightedQuickUnionUF(int N) {
count = N;
id = new int[N];
sz = new int[N];
for (int i = 0; i < N; i++) {
id[i] = i;
sz[i] = 1;
}
}
/**
* Returns the number of components.
* @return the number of components (between 1 and N)
*/
public int count() {
return count;
}
/**
* Returns the component identifier for the component containing site <tt>p</tt>.
* @param p the integer representing one site
* @return the component identifier for the component containing site <tt>p</tt>
* @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N
*/
public int find(int p) {
while (p != id[p])
p = id[p];
return p;
}
/**
* 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 <tt>true</tt> if the two sites <tt>p</tt> and <tt>q</tt>
* are in the same component, and <tt>false</tt> otherwise
* @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N
*/
public boolean connected(int p, int q) {
return find(p) == find(q);
}
/**
* Merges the component containing site<tt>p</tt> with 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 0 <= p < N and 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 (sz[rootP] < sz[rootQ]) { id[rootP] = rootQ; sz[rootQ] += sz[rootP]; }
else { id[rootQ] = rootP; sz[rootP] += sz[rootQ]; }
count--;
}
/**
* Reads in a sequence of pairs of integers (between 0 and N-1) from standard input,
* where each integer represents some object;
* if the objects are in different components, merge the two components
* and print the pair to standard output.
*/
public static void main(String[] args) {
int N = StdIn.readInt();
WeightedQuickUnionUF uf = new WeightedQuickUnionUF(N);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.connected(p, q)) continue;
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
Weighted Quick-Union在极端情况下,union方法的时间复杂度需要O(lgN),是否能对该算法进一步优化呢?答案是肯定的——使用路径压缩算法(Weighted Quick-Union with Path Compression)
private int root(int i)
{
while (i != id[i])
{
id[i] = id[id[i]];//only one extra line of code
i = id[i];
}
return i;
}| algorithm | worst-case time |
| quick-union | M N |
| weighted QU | N + M log N |
| weighted QU + path compression | N + M lg* N |
460



被折叠的 条评论
为什么被折叠?



