您的位置:首页 > 理论基础 > 数据结构算法

数据结构实验 第一单元 集合交并

2015-11-27 21:12 405 查看
引用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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: