關於並查集、帶權並查集的概念,不做過多描述,本文僅做代碼記錄,給出並查集的Java實現。
本實現中,根節點存儲根節點所屬的樹的權值,權值用負數表示。-1則表示該樹僅有根節點一個點。-2,-3以此類推
我們使用父數組和權值策略將較小樹的根連接到較大樹的根
○如果連接(p,q)中的樹的大小相等,則通過將 p 的根連接到 q 的根。
測試用例:
package Test;
import org.junit.Test;
import static org.junit.Assert.*;
public class WeightedQuickUnionDSTest {
@Test
public void testWeightedQUDS_1() {
WeightedQuickUnionDS ds = new WeightedQuickUnionDS(4);
ds.connect(1, 0);
assertEquals(true, ds.isConnected(1, 0));
assertEquals(0, ds.parent(1));
assertEquals(-2, ds.parent(0));
ds.connect(3, 2);
assertEquals(false, ds.isConnected(2, 1));
ds.connect(3, 1);
assertEquals(true, ds.isConnected(2, 1));
assertEquals(0, ds.parent(2));
assertEquals(4, ds.sizeOf(1));
}
@Test(expected = IllegalArgumentException.class)
public void validateTest_1() {
WeightedQuickUnionDS ds = new WeightedQuickUnionDS(5);
ds.validate(10);
}
// add your own Unit Tests and Integration Tests here
}
1.WeightedQuickUnionDS CONSTRUCTOR
● 完成 the constructor public WeightedQuickUnionDS(int N).
● 它創建了一個不相交集數據結構,包含 N 個元素,0 到 N-1。
●最初,每個元素都在自己的集合中。
2.WeightedQuickUnionDS VALIDATE
●完成方法 void validate(int p).
●它驗證 p 是有效的 元素/索引.
●如果 p 不是一個有效的索引,拋出一個 IllegalArgumentException
● Complete the method void validate(int p).
● It validates that p is a valid element/index.
● If p is not a valid index, throw an IllegalArgumentException as in the test case 2 below.
3. WeightedQuickUnionDS SIZE OF
●完成方法 int sizeOf(int p)。
●返回集合元素 p 所屬的大小。
5.WeightedQuickUnionDS IS CONNECTED
●完成方法 boolean isConnected(int p, int q).
●如果 p 和 q 連接/在同一組中,則返回 true,否則爲假。
●如果 p 或 q 不是有效索引,則拋出 IllegalArgumentException。
6.WeightedQuickUnionDS CONNECT
●完成方法 void connect(int p,int q)。
●通過組合包含的集合,將兩個元素 p 和 q 連接在一起 它們把小樹根和大樹根連接起來。
○如果樹的大小相等,則通過將 p 的根連接到 q 的根來斷開連接。
●如果 p 或 q 不是有效索引,則拋出 IllegalArgumentException。
上代碼:
package Test;
public class WeightedQuickUnionDS {
private int[] parent;
/*
* Returns the parent of element p.
* If p is the root of a tree, returns the negative size
* of the tree for which p is the root.
*/
public int parent(int p) {
return parent[p];
}
/* Prints the parents of the elements, separated by a space */
public void printParent() {
for (int element : parent) {
System.out.print(element + " ");
}
System.out.println();
}
/*
***************************
* DO NOT MODIFY CODE ABOVE
***************************
*/
/*
***** HELPER METHODS START *****
*/
// Add your own helper methods here
// INCLUDE your helper methods in your submission !
/*
***** HELPER METHODS END *****
*/
// EXERCISE 12.3 CONSTRUCTOR
/**
* Creates a Disjoint Sets data structure with n elements,
* 0 through n-1.
* Initially, each element is in its own set.
* @param N the number of elements
*/
public WeightedQuickUnionDS(int N) {
parent = new int[N];
for(int i=0;i<N;i++) this.parent[i] = -1;
}
// EXERCISE 12.4 VALIDATE
/**
* Validates that p is a valid element/index.
* @throws IllegalArgumentException if p is not a valid index.
*/
public void validate(int p) {
if(p<0||p>=this.parent.length) {
throw new IllegalArgumentException();
}
}
// ASSIGNMENT 12.1 SIZE OF
/**
* Returns the size of the set element p belongs to.
* @param p an element
* @return the size of the set containing p
*/
public int sizeOf(int p) {
int result = 0;
if(p<0||p>=this.parent.length) {
throw new IllegalArgumentException();
}
if(this.parent[p]<0) {
result = (0-this.parent[p]);
}else {
int pparent = this.parent[p];
while(pparent>=0) {
pparent = this.parent[pparent];
}
result = (0-pparent);
}
return result;
}
// ASSIGNMENT 12.2 IS CONNECTED
/**
* Returns true iff elements p and q are connected.
* @param p an element
* @param q the other element
* @return true if p and q are in the same set
* false otherwise
* @throws IllegalArgumentException if p or q is not a valid index.
*/
public boolean isConnected(int p, int q) {
if(p<0||p>=this.parent.length||q<0||q>=this.parent.length) {
throw new IllegalArgumentException();
}
if(p==q) return true;
//查找p,q根節點下標
int proot = p,qroot = q;
//判斷p,q是否是根節點
if(this.parent[p]>=0) {
while (this.parent[proot]>=0) {
proot = this.parent[proot];
}
}
if(this.parent[q]>=0) {
while(this.parent[qroot]>=0) {
qroot = this.parent[qroot];
}
}
return (proot==qroot?true:false);
}
// ASSIGNMENT 12.3 CONNECT
/**
* Connects two elements p and q together,
* by combining the sets containing them.
* @param p an element
* @param q the other element
* @throws IllegalArgumentException if p or q is not a valid index.
*/
public void connect(int p, int q) {
if(p<0||p>=this.parent.length||q<0||q>=this.parent.length) {
throw new IllegalArgumentException();
}
//判斷兩元素是否是同一集合
if(p!=q) {
//查找p,q根節點下標
int proot = p,qroot = q;
//判斷p,q是否是根節點
if(this.parent[p]>=0) {
while (this.parent[proot]>=0) {
proot = this.parent[proot];
}
}
if(this.parent[q]>=0) {
while(this.parent[qroot]>=0) {
qroot = this.parent[qroot];
}
}
boolean connected = (proot==qroot?true:false);
if(!connected) {
//計算兩樹誰大
int psize = this.parent[proot];
int qsize = this.parent[qroot];
//小樹合併進大樹
if(psize >= qsize) { //p合併進q
//更新大集合的size
this.parent[qroot] = (psize+qsize);
//更改p的根
this.parent[proot] = qroot;
}else { //q合併進p
this.parent[proot] = (psize+qsize);
this.parent[qroot] = proot;
}
}
}
}
public static void main(String[] args) {
WeightedQuickUnionDS ds = new WeightedQuickUnionDS(4);
ds.connect(1, 0);
ds.connect(3, 2);
ds.connect(3, 1);
ds.printParent();
}
}