並查集

/*
* 將多個集合合併成沒有交集的集合。
 給定一個字符串的集合,格式如:{aaa,bbb,ccc},{bbb,ddd},{eee,fff},{ggg},{ddd,hhh}要求將其中交集不爲空的集合合併,要求合併完成後的集合之間無交集,
 例如上例應輸出{aaabbbcccdddhhh},{eeefff},{ggg}。
(1)請描述你解決這個問題的思路;
(2)請給出主要的處理流程,算法,以及算法的複雜度;
(3)請描述可能的改進。
 
 解:
 1.對字符集合進行依次編號,分別爲[0,1,2,3,4]。若是將{{aaa,bbb,ccc},{bbb,ddd},{eee,fff},{ggg},{ddd,hhh}}看作成二維數組,編號對應二維數組的下標。
    初始化一個數組int father[] = {0,1,2,3,4};,表明其下標。
    將字符串集合放到list<Set<String>>中集合resList
 2.建立一個Map<String,List<Integer>>,key爲字符串,value爲字符串所在的編號。遍歷集合找出每一個字符串的編號,以下:
    aaa 0
    bbb 0,1
    ccc 0
    ddd 1,4
    eee 2
    fff 2
    ggg 3
    hhh 4
 3.合併,合併的時候將編號大的集合合併到小的集合裏面。方法是:遍歷map中的List<Integer>,更新father對應的下表,以下:
    aaa 0       {0,1,2,3,4}
    bbb 0 1     {0,0,2,3,4}
    ccc 0       {0,0,2,3,4}
    ddd 1 4     {0,0,2,3,0}
    eee 2       {0,0,2,3,0}
    fff 2       {0,0,2,3,0}
    ggg 3       {0,0,2,3,0}
    hhh 4       {0,0,2,3,0}
    以後遍歷father數組,若是i!=faterh[i],則
        Set<String> dest = resList.get(father[i]);
        Set<String> sour = resList.get(i);
        sour.addAll(dest);
*/
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Arrays;
public class ShowDisjointSet{

    private List<Set<String>> resList = new ArrayList<Set<String>>();
    private int[] father;
    private int len;

    public static void main(String args[]){
        String[] str0 = {"aaa","bbb","ccc"};
        String[] str1 = {"bbb","ddd"};
        String[] str2 = {"eee","fff"};
        String[] str3 = {"ggg"};
        String[] str4 = {"ddd","hhh"};
        String[][] arr = {str0,str1,str2,str3,str4};
        
        ShowDisjointSet obj = new ShowDisjointSet();
        obj.getResList(arr);

    }

    // 1:並查集
    public void getResList(String[][] arr){
        len = arr.length;
        // 初始化resList
        for(String[] tmp:arr){
            Set<String> set = new HashSet<String>();
            set.addAll(Arrays.asList(tmp));
            resList.add(set);
        }
        // 初始化數組
        father = new int[len];
        for(int i=0;i<len;i++){
            father[i] = i;
        }
        Map<String,List<Integer>> map = getRes(arr);
        unionSet(map);
        System.out.println(resList);
    }

    // 2:遍歷集合
    public Map<String,List<Integer>> getRes(String[][] arr){
        Map<String,List<Integer>> map = new HashMap<String,List<Integer>>();
        for(int i=0; i<len; i++){
            for(String tmp:arr[i]){
                if(!map.containsKey(tmp)){
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(i);
                    map.put(tmp,list);
                }else{
                    map.get(tmp).add(i);
                }
            }
        }
        return map;
    }

    // 3:合併集合
    public void unionSet(Map<String,List<Integer>> map){
        Iterator<Map.Entry<String,List<Integer>>> ite = map.entrySet().iterator();
        while(ite.hasNext()){
            Map.Entry<String,List<Integer>> entry = ite.next();
            String key = entry.getKey();
            List<Integer> value = entry.getValue();
            unionHelp(value);
            System.out.println(key+":"+value);
        }

        System.out.println("the father array is "+ Arrays.toString(father));

        for(int i=0; i<len; i++){
            if(i != father[i]){
                Set<String> dest = resList.get(father[i]);
                Set<String> sour = resList.get(i);
                dest.addAll(sour);
            }
        }

        for(int i=0; i<len; i++){
            if(i != father[i]){
                resList.get(i).clear();
            }
        }

    }

    public void unionHelp(List<Integer> list){
        int min = getFather(list.get(0));
        int size = list.size();
        for(int i=0; i<size; i++){
            father[list.get(i)] = min;
        }
    }
    
    public int getFather(int index){
        while(index!=father[index]){
            index = father[index];
        }
        return index;
    }

}
相關文章
相關標籤/搜索