使用單鏈表來實現集合的交並差運算 數據結構
問題描述
該算法的設計,要求運行結果如下所示:
集合的運算如下:
原 集 合A: c a e h
原 集 合B: f h b g d a
有序集合A: a c e h
有序集合B: a b d f g h
集合的並C: a b c d e f g h
集合的交C: a h
集合的差C: c e
代碼實現
首先這里交並差的實現是基於鏈表中的元素已經從小到大排完序的鏈表。這里排序使用的是冒泡排序。
//鏈表的冒泡排序算法
bool BubbleSort(LinkList &L) //鏈表的冒泡排序
{
LinkList p, q, tail;
tail=NULL;
while((L->next->next)!=tail)
{
p=L;
q=L->next;
while(q->next!=tail)
{
if((q->data) > (q->next->data))
{
p->next=q->next;
q->next=q->next->next;
p->next->next=q;
q=p->next;
}
q=q->next;
p=p->next;
}
tail=q;
}
return true;
}
//集合的並
bool merge(LinkList &L1, LinkList &L2, LinkList &L3)//集合的並 這里的集合已經排序
{
LinkList p1=L1->next, p2=L2->next, p3=L3, s;
while(p1!=NULL && p2!=NULL)
{
if(p1->data!=p2->data)
{
if(p1->data > p2->data)
swap(p1, p2);
while(p1!=NULL && p1->data < p2->data)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
}
else
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
p2=p2->next;
}
}
if(p2!=NULL) //這里統一讓p1代表鏈表中還有剩余元素的那條鏈
p1=p2;
while(p1!=NULL)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
return true;
}
//集合的交
bool intersect(LinkList &L1, LinkList &L2, LinkList &L3)//集合的交 這里的集合已經排序
{
LinkList p1=L1->next, p2=L2->next, p3=L3, s;
if(p1==NULL || p2==NULL)//兩者中有一個是空鏈表
return false;
while(p1!=NULL)
{
while(p2!=NULL)
{
if(p2->data==p1->data)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
}
if(p2->data > p1->data)
break;
p2=p2->next;
}
p1=p1->next;
}
return true;
}
//集合的差
bool differ(LinkList &L1, LinkList &L2, LinkList &L3) //集合的差 這里的集合已經排序
{
LinkList p1=L1->next, p2=L2->next, p3=L3, s;
if(p1->next==NULL)
return false;
while(p1!=NULL && p2!=NULL)
{
if(p1->data!=p2->data)
{
if(p1->data > p2->data)
{
while(p1->data > p2->data ) //這里要保證p2后面的值也要不能大於p1當前的值
{
p2=p2->next;
}
if(p1->data==p2->data)
continue;
}
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
else
{
p1=p1->next;
p2=p2->next;
}
}
while(p1!=NULL)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
return true;
}
//完整的代碼實現
#include<bits/stdc++.h>
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode, *LinkList;
bool init(LinkList &L)
{
L=(LinkList)malloc(sizeof(LNode));
if(L==NULL)
return false;
L->next=NULL;
return true;
}
bool search(LinkList &L, int x)
{
LinkList p=L->next;
while(p)
{
if(p->data==x)
return false;
p=p->next;
}
return true;
}
bool creat_list(LinkList &L, char a[], int n) //采用尾插法建立單鏈表
{
LinkList p=L, s;
for(int i=0; i<n; i++)
{
if(search(L, a[i])==false)
continue;
s=(LinkList)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data=a[i];
s->next=NULL;
p->next=s;
p=s;
}
return true;
}
bool display(LinkList &L)
{
LinkList p=L->next;
if(p==NULL)
return false;
while(p)
{
printf("%c ", p->data);
p=p->next;
}
printf("\n");
return true;
}
bool clear(LinkList &L)
{
LinkList p;
while(L)
{
p=L->next;
free(L);
L=p;
}
L=NULL;
return true;
}
bool BubbleSort(LinkList &L) //鏈表的冒泡排序
{
LinkList p, q, tail;
tail=NULL;
while((L->next->next)!=tail)
{
p=L;
q=L->next;
while(q->next!=tail)
{
if((q->data) > (q->next->data))
{
p->next=q->next;
q->next=q->next->next;
p->next->next=q;
q=p->next;
}
q=q->next;
p=p->next;
}
tail=q;
}
return true;
}
bool merge(LinkList &L1, LinkList &L2, LinkList &L3)//集合的並 這里的集合已經排序
{
LinkList p1=L1->next, p2=L2->next, p3=L3, s;
while(p1!=NULL && p2!=NULL)
{
if(p1->data!=p2->data)
{
if(p1->data > p2->data)
swap(p1, p2);
while(p1!=NULL && p1->data < p2->data)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
}
else
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
p2=p2->next;
}
}
if(p2!=NULL) //這里統一讓p1代表鏈表中還有剩余元素的那條鏈
p1=p2;
while(p1!=NULL)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
return true;
}
bool intersect(LinkList &L1, LinkList &L2, LinkList &L3)//集合的交 這里的集合已經排序
{
LinkList p1=L1->next, p2=L2->next, p3=L3, s;
if(p1==NULL || p2==NULL)//兩者中有一個是空鏈表
return false;
while(p1!=NULL)
{
while(p2!=NULL)
{
if(p2->data==p1->data)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
}
if(p2->data > p1->data)
break;
p2=p2->next;
}
p1=p1->next;
}
return true;
}
bool differ(LinkList &L1, LinkList &L2, LinkList &L3) //集合的差 這里的集合已經排序
{
LinkList p1=L1->next, p2=L2->next, p3=L3, s;
if(p1->next==NULL)
return false;
while(p1!=NULL && p2!=NULL)
{
if(p1->data!=p2->data)
{
if(p1->data > p2->data)
{
while(p1->data > p2->data ) //這里要保證p2后面的值也要不能大於p1當前的值
{
p2=p2->next;
}
if(p1->data==p2->data)
continue;
}
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
else
{
p1=p1->next;
p2=p2->next;
}
}
while(p1!=NULL)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p1->data;
s->next=NULL;
p3->next=s;
p3=s;
p1=p1->next;
}
return true;
}
/*
產生n個[min, max]的隨機數。可能會有重復值。
*/
void initRandomize(int *arr, int n, int min, int max)
{
int i = 0;
srand(time(0)); /*設置種子,並生成偽隨機序列*/
for (i = 0; i < n; ++i) {
arr[i] = rand() % (max - min + 1) + min; /*得到從[min, max]之間的隨機數*/
printf("%d ", arr[i]);
}
printf("\n\n");
}
int main()
{
int cnt=0, i, e, tmp;
char a[]={'c', 'a', 'e', 'h','e'};
char b[]={'f', 'h', 'b', 'g', 'd', 'a', 'b'};
LinkList L1, L2, L3;
if(!init(L1) || !init(L2) || !init(L3))
{
cout<<"初始化鏈表失敗,程序退出\n";
return 0;
}
cout<<"L1\n";
//initRandomize(a, 10, 0, 10);
creat_list(L1, a, 5);//使用尾插法來創建鏈表
display(L1);
BubbleSort(L1);
display(L1);
cout<<endl<<endl;
cout<<"L2\n";
//initRandomize(a, 10, 0, 10);
creat_list(L2, b, 7);//使用尾插法來創建鏈表
display(L2);
BubbleSort(L2);
display(L2);
cout<<endl<<endl;
cout<<"L1和L2的並\n";
merge(L1, L2, L3);
display(L3);
clear(L3);
init(L3);
cout<<"\nL1和L2的交\n";
intersect(L1, L2, L3);
display(L3);
clear(L3);
init(L3);
cout<<"\nL1和L2的差\n";
differ(L1, L2, L3);
display(L3);
if(clear(L1))
cout<<"L1 free成功\n";
else cout<<"L1 free失敗\n";
if(clear(L2))
cout<<"L2 free成功\n";
else cout<<"L2 free失敗\n";
if(clear(L3))
cout<<"L3 free成功\n";
else cout<<"L3 free失敗\n";
return 0;
}
