引用LinkedList.h和string.h
头文件ColletionOpr.h
里面有一些操作集合的算法
//求两个集合的并集 LinkedList* UnionCollection(LinkedList *LA,LinkedList *LB) { LinkedList *ans,*ele; DataType* dt; int lenA = GetListLength(LA), lenB = GetListLength(LB), len, i, j, exist; /* 一、算法思路: 1. 将A中 所有元素 填入ans中。 2. 对于B中的元素,若 不存在于ans中 则加入到ans中。 时间复杂度: 第一步的 填入ans 中采用 ToArray(O(lenA))、CreateListR(O(lenA))方法时间复杂度为:O(lenA)。 第二步中 遍历B元素 执行GetListElem(O(lenB)) 、LocateListElem(O(lenB)), 由于在for循环中,复杂度为:O(lenB^2)。 故整个算法的时间复杂度为: O(lenA + lenB^2) 二、算法优化: 优化1: 分析算法可知,将 A、B中长度较短 的放在后面遍历比较合适。 第一步填入ans的时候,将A、B两者中长度较长的填入ans中。 这样可以降低第二次遍历集合时候的次数 优化后复杂度为: O(len(较长的) + len(较短的)^2) 优化2: 三、算法缺点: ① 长度较长的那个集合中所有元素均是互异的,否则ans中将出现重复元素。 四、算法修正: 为弥补 三 提出的算法缺点。 在将较长集合填入ans时,应检查重复性。 修正后算法复杂度为: O(lenA^2+lenB^2) 由此可见,修正后的算法使得 优化1 无效。 */ //代码如下: // //1.将A中 所有元素 填入ans中。 //优化1:将较长元素放在A /*if(lenA<lenB) { LinkedList *ltemp=LA; LA=LB; LB=ltemp; int itemp=lenA; lenA=lenB; lenB=itemp; }*/ //dt = ToArray(LA,&len); //ans = CreateListR(dt,len); //以下为修正的算法,替换以上。目的是检查重复性。 //时间复杂度为:O(lenA^2) dt = ToArray(LA, &len);//O(lenA) ans = CreateListR(NULL, 0);//创建空表 len = 0;//ans的长度 for (i = 0; i < lenA; i++) { exist = 0; for (j = 0; j < i; j++) { if (dt[i] == dt[j]) { exist = 1; break; } } if (!exist) { len++; InsertList(ans, len, dt[i]); } }//O(lenA^2) //2. 对于B中的元素,若 不存在于ans中 则加入到ans中。 for(i=1;i<=lenB;i++) { ele=GetListElem(LB,i); if(LocateListElem(ans,ele->data)==NULL) { //添加到ans中 len++; InsertList(ans,len,ele->data); } } return ans; } //求两个集合的交集 LinkedList* InterCollection(LinkedList *LA,LinkedList *LB) { LinkedList *ans = CreateListR(NULL,0), *ele; int lenA=GetListLength(LA), lenB=GetListLength(LB), len=0, i,j,exist; /* 算法思路: 1. 遍历A和B中,长度较短的集合。 2. 若另外一个集合中也存在这个元素,则将这个元素添加到ans中。 时间复杂度: for循环 :O(lenA) GetListElem : O(lenA) LocateListElem : O(lenB) LocateListElem : O(len(ans)) 故总时间复杂度为:O(lenA^2 + lenA*lenB) 由此可见将遍历较短的元素这个选择是明智的 算法缺点: 暂时没发现 */ if(lenA>lenB) { LinkedList *ltemp=LA; LA=LB; LB=ltemp; int itemp=lenA; lenA=lenB; lenB=itemp; } //此时A必定是A,B中长度较短的 for(i=1;i<=lenA;i++) { ele=GetListElem(LA,i); if(LocateListElem(LB,ele->data)!=NULL) { //B中存在这个元素 //避免ans中重复元素。 if (LocateListElem(ans, ele->data)==NULL) { len++; InsertList(ans, len, ele->data); } } } return ans; } void TestColletionOpr() { LinkedList *listA,*listB,*unionAns,*interAns; char A[100001], B[100001]; printf("计算两个集合的交集和并集,集合的长度不超过100000\n"); printf("集合A:"); scanf("%s",A); printf("集合B:"); scanf("%s",B); //创建链表,尾插法。 listA=CreateListR(A,strlen(A)); listB=CreateListR(B,strlen(B)); unionAns=UnionCollection(listA,listB); interAns=InterCollection(listA,listB); printf("A∪B="); PrintListInline(unionAns); printf("A∩B="); PrintListInline(interAns); }