zoukankan      html  css  js  c++  java
  • 【转载】多个集合合并成没有交集的集合-实现

    原博文地址http://www.cnblogs.com/ttltry-air/archive/2012/08/14/2638437.html

    1、问题描述

    将多个集合合并成没有交集的集合。 
    给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出{aaa bbb ccc ddd hhh},{eee fff}, {ggg}。 
    (1)请描述你解决这个问题的思路; 
    (2)请给出主要的处理流程,算法,以及算法的复杂度 
    (3)请描述可能的改进。

    2、分析

    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            
        bbb: 0, 1         
        ccc: 0           
        ddd: 1, 4        
        eee: 2            
        fff: 2           
        ggg: 3            
        hhh: 4           
        所以合并完后有三个集合,第0,1,4个集合合并到了一起, 
        第2,3个集合没有进行合并。

    3、具体实现

       1: class DisjointSetProblem {
       2:     private final int SIZE = 7;
       3:     private int[] father;  
       4:     private static List<Set<String>> resultList = new ArrayList<Set<String>>();
       5:  
       6:     public static void main(String[] args) {
       7:         String[] str0 = { "aaa", "bbb", "ccc", };
       8:         String[] str1 = { "bbb", "ddd", };
       9:         String[] str2 = { "eee", "fff", };
      10:         String[] str3 = { "ggg", };
      11:         String[] str4 = { "ddd", "hhh", };
      12:         String[] str5 = { "xx", "yy", };
      13:         String[] str6 = { "zz", "yy", };
      14:         String[][] strs = { str0, str1, str2, str3, str4, str5, str6 };
      15:         //change String[][] to List<Set>  
      16:         for (String[] str : strs) {
      17:             //when I write--"Arraylist list=Arrays.asList(strArray)","addAll()" is unsupported for such a arraylist.  
      18:             Set<String> set = new HashSet<String>();
      19:             set.addAll(Arrays.asList(str));
      20:             resultList.add(set);
      21:         }
      22:         DisjointSetProblem disjointSet = new DisjointSetProblem();
      23:         disjointSet.disjoin(strs);
      24:     }
      25:  
      26:     /*
      27:      * 获取hashmap过程
      28:      * */
      29:     public void disjoin(String[][] strings) {
      30:         if (strings == null || strings.length < 2)
      31:             return;
      32:         initial();
      33:         // 获得hash_map:key为字符串,value为一个链表
      34:         Map<String, List<Integer>> map = storeInHashMap(strings);
      35:         // 并查集进行合并
      36:         union(map);
      37:     }
      38:  
      39:     //in the beginning,each element is in its own "group".  
      40:     public void initial() {
      41:         father = new int[SIZE];
      42:         for (int i = 0; i < SIZE; i++) {
      43:             father[i] = i;
      44:         }
      45:     }
      46:  
      47:     /* Map<k,v> 
      48:      * key:String 
      49:      * value:List<Integer>-in which sets the string shows up. 
      50:      */
      51:     public Map<String, List<Integer>> storeInHashMap(String[][] strings) {
      52:         Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
      53:         for (int i = 0; i < SIZE; i++) {
      54:             for (String each : strings[i]) {
      55:                 if (!map.containsKey(each)) {
      56:                     List<Integer> list = new ArrayList<Integer>();
      57:                     list.add(i);
      58:                     map.put(each, list);
      59:                 } else {
      60:                     map.get(each).add(i);
      61:                 }
      62:             }
      63:         }
      64:  
      65:         // 打印出map
      66:         System.out.println("集合映射所生成的hashmap为:");
      67:         printMap(map);
      68:         return map;
      69:     }
      70:  
      71:     private void printMap(Map<String, List<Integer>> map) {
      72:         // TODO Auto-generated method stub
      73:         Iterator<Map.Entry<String, List<Integer>>> iter = map.entrySet()
      74:                 .iterator();
      75:         while (iter.hasNext()) {
      76:             Map.Entry<String, List<Integer>> entry = iter.next();
      77:             String key = entry.getKey();
      78:             List<Integer> value = entry.getValue();
      79:             System.out.println(key + ":" + value);
      80:         }
      81:         System.out.println();
      82:     }
      83:  
      84:     /*
      85:      * 对hashmap进行并查集合并操作
      86:      * */
      87:     public void union(Map<String, List<Integer>> map) {
      88:         Iterator<Map.Entry<String, List<Integer>>> it = map.entrySet()
      89:                 .iterator();
      90:         while (it.hasNext()) {
      91:             Map.Entry<String, List<Integer>> entry = it.next();
      92:             List<Integer> value = entry.getValue();
      93:             unionHelp(value);//the arrays whose indexes are in the same list should be merged to one set.             
      94:         }
      95:         // 打印出father父节点信息
      96:         System.out.println("hashmap集合合并之后的父节点信息为:");
      97:         printFather(father);//System.out.println("the father array is " + Arrays.toString(father));
      98:         printSetList(resultList);
      99:         //merge two sets  
     100:         for (int i = 0; i < SIZE; i++) {
     101:             if (i != father[i]) {
     102:                 // set:无重复元素
     103:                 Set<String> dest = resultList.get(father[i]);
     104:                 Set<String> source = resultList.get(i);
     105:                 dest.addAll(source);
     106:             }
     107:         }
     108:         //clear a set which has been added.  
     109:         // 当B集合添加到A集合后,清空B集合
     110:         for (int i = 0; i < SIZE; i++) {
     111:             if (i != father[i]) {
     112:                 resultList.get(i).clear();
     113:             }
     114:         }
     115:         System.out.println("合并后:" + resultList);
     116:     }
     117:  
     118:     public void unionHelp(List<Integer> list) {
     119:         int minFather = getFather(list.get(0));//list[0] is the smaller.  
     120:         // 传过来的list参数已经排好序
     121:         for (int i = 0, size = list.size(); i < size; i++) {
     122:             //father[list.get(i)] = minFather;
     123:             unionHelp(list.get(0),list.get(i));
     124:         }
     125:     }
     126:  
     127:     // 路径压缩
     128:     public int getFather(int x) {
     129:         while (x != father[x]) {
     130:             x = father[x];
     131:         }
     132:         return x;
     133:     }    
     134:  
     135:     private void printFather(int[] fatherNode) {
     136:         // TODO Auto-generated method stub
     137:         for (int node : fatherNode)
     138:             System.out.print(node + " ");
     139:         System.out.println();
     140:     }
     141:  
     142:     private void printSetList(List<Set<String>> list) {
     143:         // TODO Auto-generated method stub
     144:         System.out.print("合并前:");
     145:         for (int i = 0; i < SIZE; i++) {
     146:             System.out.print(list.get(i) + " ");
     147:         }
     148:         System.out.println();
     149:     }
     150:  
     151:     //general union in disjoin set.But we overload it in this case.  
     152:     public void unionHelp(int x, int y) {
     153:         if (father[x] != father[y]) {
     154:             int fx = getFather(x);
     155:             int fy = getFather(y);
     156:             //merge two arrays to the array that has a smaller index.  
     157:             if (fx < fy) {
     158:                 father[y] = fx;
     159:             } else {
     160:                 father[x] = fy;
     161:             }
     162:         }
     163:     }
     164:     
     165: }
    

      

  • 相关阅读:
    EF中連表查詢的應用方式
    排序刷新及其分頁
    SpringMVC与前台的json数据交互
    最详细的springmvc-mybatis教程
    数据库主从复制
    display:inline、block、inline-block的区别
    Yii框架中有关于layout的说明
    创建yii的第一个应用
    学习bootstrap的总结文章
    数据库事物隔离级别通俗理解
  • 原文地址:https://www.cnblogs.com/yujianshiguang/p/5285602.html
Copyright © 2011-2022 走看看