(二)1.1_线性表求集合的并集

一.集合求并集一般算法

1.思路分析:
 有两个集合A和B,用线性表L1,L2表示,求他们的并集,一般我们都会想到的方法:用两个循环遍历两个线性表L1,L2中的元素,把L2中的元素与L1中的元素依次比较,如果L2中的元素不和L1中的元素相同,则把L2中这个元素存到L1的末尾,否则不存.

2.代码实现

 //集合求并集,这里使用顺序表表示集合 
void  Union(SqList *L1,SqList *L2)
{    
    for(elemType* p=L2->elem;p<(L2->elem+L2->length);++p)       //遍历L2中的所有元素 
    {   	
    	int rear=L1->length;                //顺序表L1的末尾索引序号等于已存元素的数量 
		bool add=true;                      //是否添加的标记变量,初始为真 
    	
    	for(elemType* q=L1->elem;q<(L1->elem+L1->length);++q)     //遍历L1中的所有元素
    	{   	
            if(*p==*q)                     //如果L2中遍历到的元素与L1中的某个元素相同 
            add=false;	             	   //则添加标记为假 
		}   	
    	if(add)                            //如果添加标记为真 
    	{
    		L1->elem[rear]=*p;            //把L2中遍历到这个的元素添加到L1的末尾 
            ++(L1->length);               //L1的元素数量加1 
		}       
	}	
} 

这是非常普通的算法,且时间复杂度过高,以下有一种快速求集合的算法,但是只适用于有序集合.

二.有序集合求并集快速算法

1.思路分析:
  有两个有序递增集合A和B,用线性表L1,L2表示,求他们的并集.我们先创建一个新的线性表L3,用来存储并集.初始我们用两个指针分别指向线性表L1,L2的头部,对他们的元素都只遍历1次,没错,只从头到尾遍历一次.在遍历的过程中,对两个指针所指向的元素进行比较,哪个指针指向的元素更小,就把这个元素存入L3中,然后指针下移.而另一个指针不能动.假如相等,就取其中一个元素存入L3中,两个指针同时下移.直到有一个线性表被遍历完,然后把另一个线性表剩下的元素依次存入L3中.

2.代码实现

 //有序集合求并集(递增集合),这里使用顺序表表示集合 
void  MergeList(SqList *L1,SqList *L2,SqList *L3)
{
   elemType *p=L1->elem;                        //指向L1的指针 
   elemType *q=L2->elem;                        //指向L2的指针
   elemType *r=L3->elem;                        //指向L3的指针
    
    for(L3->length=0;p<(L1->elem+L1->length)&&q<(L2->elem+L2->length);L3->length++)
    {   	
          if(*p==*q)                     //两指针所指元素相等情况 
          {
          	 r[L3->length]=*(p++);      //这里相等的情况我们都取L1的元素,且指针下移,当然也可以取L2中的元素,因为是一样的,没什么影响 
          	 q++;                       //指向L2的指针也下移 
		  }
		  else                          //两指针所指元素不相等情况
             r[L3->length]=(*p)<(*q)?*(p++):*(q++);		    //取两指针指向的更大的那个元素,并且那个指针下移 
	}
	
	while(p<(L1->elem+L1->length))        //如果是L1中的元素有剩余没有被遍历到 
	{
		r[L3->length++]=*(p++);          //剩余元素通过循环依次加入到L3的末尾 
		
	}	  
		while(q<(L2->elem+L2->length))   //如果是L2中的元素有剩余没有被遍历到
	{
		r[L3->length++]=*(q++);         //剩余元素通过循环依次加入到L3的末尾 
	}
}            //注意:上面两个while语句只有其中一个会被执行

这里可能有人又有疑问了,要是我的集合是递减的怎么办?那原理还是不变,我们就把比较两指针指向的更小元素存入线性表L3改成更大元素存入线性表L3就行了.

三.总结
  一般算法虽然效率低但是不管集合是否有序,都能使用,快速算法虽然效率高,但是只能适用于有序集合,所以我们要根据情况来选择算法.

你可能感兴趣的:(数据结构(C语言版))