字符串集合的合並


將多個集合合並成沒有交集的集合。    
給定一個字符串的集合,格式如:{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\t",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\t",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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM