使用单链表来实现集合的交并差运算 数据结构
问题描述
该算法的设计,要求运行结果如下所示:
集合的运算如下:
原 集 合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; }