zoukankan      html  css  js  c++  java
  • 字符串集合的合并

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

    采用并查集。(关于并查集,上篇博文讲了)

    首先所有的字符串都在单独的并查集中。然后依扫描每个集合,顺序合并将两个相邻元素合并。例如,对于,首先查看aaa和bbb是否在同一个并查集中,如果不在,那么把它们所在的并查集合并,然后再看bbb和ccc是否在同一个并查集中,如果不在,那么也把 它们所在的并查集合并。接下来再扫描其他的集合,当所有的集合都扫描完了,并查集代表的集合便是所求。复杂度应该是O(NlgN)的。改进的话,首先可以 记录每个节点的根结点,改进查询。合并的时候,可以把大的和小的进行合,这样也减少复杂度。

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX 26
    
    //将给定的字符串的集合转化为如下的关系“aaa”编号为1,以此类推。。。。 
    int relation[6][2] = {
            {1,2},//{"aaa","bbb"}
            {1,3},//{"aaa","ccc"}
            {2,4},
            {5,6},
            {4,8},
            {7,7}//{ggg}
          };
    //(之所以这么复杂去实现,主要是为了输出ggg,目前使用并查集没有更好的办法) 
    //找主根(一开始初始化为-1,如果A[x]<0,首先
    //给其根节点赋值为本身并返回,其次其根节点为本身的,返回其本身。)
    //此函数主要目的是在集合合并处使用           
    int find_root(int A[], int x)
    {
    //结合调用的for循环i=0~6;故只有出现的字母才会出现自己的根节点是自己,没有出现的字母根节点仍然是-1;(为了以后再输出时方便,加以控制)    
      if(A[x]<0)
          {
              A[x]=x;
            return x;
        }
      else if(A[x]==x)
              return x;
      else
        return find_root(A, A[x]); 
    }
    //(此函数主要是在最后结果输出时使用 ) 
    //返回根节点 
    int findroot(int A[],int x)
    {
      if(A[x]==x||A[x]==-1)
        return A[x];
      else
        return findroot(A, A[x]); 
    }
    
    int main(int argc, char *argv[])
    {
      int i;
      int root1;
      int root2;
      int A[MAX];//根节点的存储 
    //一开始根节点的数组里面的值初始化为-1 
      for(i=0;i<26;i++)
        A[i] = -1;
    //遍历relation二维数组来实现集合的合并   
      for(i=0;i<6;i++)
       {
        root1 = find_root(A, relation[i][0]); 
        root2 = find_root(A, relation[i][1]);
        if(root1!=root2)//集合根节点的合并 (此处还可以优化?) 
                A[root1]=root2;
       } 
       
    //结果的输出  
       int flag[26]={0};
       for(i=1;i<26;i++)
       {
               if(flag[i])
                   continue;
               int mark=findroot(A,i);//为了输出找根节点  之前是A[i]  by felix
            //根节点为-1的不考虑 
               if(mark!=-1)
               {
                   flag[i]=1;
                   printf("%c%c%c	",i+'a'-1,i+'a'-1,i+'a'-1);
                   for(int j=i+1;j<26;j++)
                   {
                       if(flag[j])
                           continue;
                       int marks=findroot(A,A[j]);
                       if(marks==mark)
                       {
                           flag[j]=1;
                           printf("%c%c%c	",j+'a'-1,j+'a'-1,j+'a'-1);
                    }
                }
                puts("");
            }
            
       }
      system("PAUSE");    
      return 0;
    }

     方法二:使用hash_table方法

    http://www.cnblogs.com/ttltry-air/archive/2012/08/14/2638437.html

  • 相关阅读:
    pktgen使用指南
    常见的网卡调优
    网络PPS测试
    网络性能测试工具qperf
    设置虚拟机静态IP
    superset填坑
    js格式化
    《你不知道的JavaScript》读书笔记(一):JS是如何查找变量的
    技术分享PPT整理(三):网页渲染流程
    技术分享PPT整理(二):C#常用类型与数据结构
  • 原文地址:https://www.cnblogs.com/wft1990/p/6984710.html
Copyright © 2011-2022 走看看