java disjoint_java-并查集(Disjoint-set)-将多个集合合并成没有交集的集合

这篇博客介绍了如何利用Java的HashSet和HashMap实现并查集来解决将交集不为空的集合合并为无交集集合的问题。详细描述了解决思路、处理流程和算法复杂度,并提供了具体的代码示例。还讨论了可能的改进方案,以及在处理过程中遇到的错误和修正方法。
摘要由CSDN通过智能技术生成

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

public class DisjointSet {

/**

题目:给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出{aaa bbb ccc ddd hhh},{eee fff}, {ggg}。

(1)请描述你解决这个问题的思路;

(2)请给出主要的处理流程,算法,以及算法的复杂度

(3)请描述可能的改进。

解答:

1. 假定每个集合编号为0,1,2,3...

2. 创建一个hash_map,key为字符串,value为一个链表,链表节点为字符串所在集合的编号。遍历所有的集合,将字符串和对应的集合编号插入到hash_map中去。

3. 创建一个长度等于集合个数的int数组,表示集合间的合并关系。例如,下标为5的元素值为3,表示将下标为5的集合合并到下标为3的集合中去。开始时将所有值都初始化为-1,表示集合间没有互相合并。在集合合并的过程中,我们将所有的字符串都合并到编号较小的集合中去。

遍历第二步中生成的hash_map,对于每个value中的链表,首先找到最小的集合编号(有些集合已经被合并过,需要顺着合并关系数组找到合并后的集合编号),然后将链表中所有编号的集合都合并到编号最小的集合中(通过更改合并关系数组)。

4.现在合并关系数组中值为-1的集合即为最终的集合,它的元素来源于所有直接或间接指向它的集合。

0: {aaa bbb ccc}

1: {bbb ddd}

2: {eee fff}

3: {ggg}

4: {ddd hhh}

生成的hash_map,和处理完每个值后的合并关系数组分别为

aaa: 0 [-1, -1, -1, -1, -1]

bbb: 0, 1 [-1, 0, -1, -1, -1]

ccc: 0 [-1, 0, -1, -1, -1]

ddd: 1, 4 [-1, 0, -1, -1, 0]

eee: 2 [-1, 0, -1, -1, 0]

fff: 2 [-1, 0, -1, -1, 0]

ggg: 3 [-1, 0, -1, -1, 0]

hhh: 4 [-1, 0, -1, -1, 0]

所以合并完后有三个集合,第0,1,4个集合合并到了一起,

第2,3个集合没有进行合并。

Use "Disjoin-set".But I use "HashSet" and "HashMap" of Java API.Does "Disjoin-set" have its own data structure?

see also [url]http://www.csie.ntnu.edu.tw/~u91029/DisjointSets.html[/url]

*/

private final int SIZE=7;

private int[] father;//the root in disjion set.

private static List> resultList=new ArrayList>();

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[] str5={

"xx",

"yy",};

String[] str6={

"zz",

"yy",};

String[][] strs={str0,str1,str2,str3,str4,str5,str6};

//change String[][] to List

for(String[] str:strs){

//when I write--"Arraylist list=Arrays.asList(strArray)","addAll()" is unsupported for such a arraylist.

Set set=new HashSet();

set.addAll(Arrays.asList(str));

resultList.add(set);

}

DisjointSet disjointSet=new DisjointSet();

disjointSet.disjoin(strs);

}

public void disjoin(String[][] strings){

if(strings==null||strings.length<2)return;

initial();

Map> map=storeInHashMap(strings);

union(map);

}

//in the beginning,each element is in its own "group".

public void initial(){

father=new int[SIZE];

for(int i=0;i

father[i]=i;

}

}

/*Map

* key:String

* value:List-in which sets the string shows up.

*/

public Map> storeInHashMap(String[][] strings){

Map> map=new HashMap>();

for(int i=0;i

for(String each:strings[i]){

if(!map.containsKey(each)){

List list=new ArrayList();

list.add(i);

map.put(each, list);

}else{

map.get(each).add(i);

}

}

}

//traverse the hashmap

Iterator>> it=map.entrySet().iterator();

while(it.hasNext()){

Map.Entry> entry=it.next();

String key=entry.getKey();

List value=entry.getValue();

System.out.println(key+":"+value);

}

return map;

}

public void union(Map> map){

Iterator>> it=map.entrySet().iterator();

while(it.hasNext()){

Map.Entry> entry=it.next();

List value=entry.getValue();

unionHelp(value);//the arrays whose indexes are in the same list should be merged to one set.

}

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

//merge two sets

for(int i=0;i

if(i!=father[i]){

Set dest=resultList.get(father[i]);

Set source=resultList.get(i);

dest.addAll(source);

}

}

//clear a set which has been added.

for(int i=0;i

if(i!=father[i]){

resultList.get(i).clear();

}

}

System.out.println("after merge:"+resultList);

}

public void unionHelp(List list){

int minFather=getFather(list.get(0));//list[0] is the smaller.

for(int i=0,size=list.size();i

father[list.get(i)]=minFather;

}

}

//general union in disjoin set.But we overload it in this case.

public void unionHelp(int x,int y){

if(father[x]!=father[y]){

int fx=getFather(x);

int fy=getFather(y);

//merge two arrays to the array that has a smaller index.

if(fx

father[y]=fx;

}else{

father[x]=fy;

}

}

}

public int getFather(int x){

while(x!=father[x]){

x=father[x];

}

return x;

}

}

0

10

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2012-04-28 00:02

浏览 7587

评论

2 楼

zzy88825

2013-04-16

第153行需要改为father[getFather(list.get(i))] = minFather;

不然这种[[aaa, ccc, bbb], [ddd, bbb], [fff, eee], [hhh], [hhh, ddd], [yy, xx], [zz, yy]]情况也会处理错误

1 楼

zzy88825

2013-04-16

第136行的Set dest=resultList.get(father[i]); 不对

应该是Set dest=resultList.get(getFather(i)); 不然算出的结果是错误的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值