Java實現帶權並查集Weighted Quick Union Disjoint Sets

關於並查集、帶權並查集的概念,不做過多描述,本文僅做代碼記錄,給出並查集的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();
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章