資料結構:求集合差集(c/c++)
阿新 • • 發佈:2019-02-14
用帶頭結點的單鏈表表示整數集合,完成以下演算法並分析時間複雜度:
(1)設計一個演算法求兩個集合A和B的差集運算,即C=A-B,要求演算法的空間複雜度為O(1),並釋放單鏈表A和B中不需要的結點。
(2)假設集合中的元素按遞增排列,設計一個高效演算法求兩個集合A和B的差集運算,即C=A-B,要求演算法的空間複雜度為O(1),並釋放單鏈表A和B中不需要的結點。
#include<stdio.h> #include<stdlib.h> typedef struct LNode { int data; struct LNode* next; } LinkNode; void DestroyList(LinkNode*L) //銷燬線性表函式 { LinkNode*p=L->next,*q=L; while(p!=NULL) { free(q); q=p; p=p->next; } free(q); } void DispList(LinkNode*L) //輸出函式 { LinkNode*p=L->next; while(p!=NULL) { printf("%d ",p->data); p=p->next; } printf("\n"); } void CreatList(LinkNode*&L,int a[],int n) //陣列資料建立連結串列函式尾插法 { LinkNode*p,*q; L=(LinkNode* )malloc(sizeof(LinkNode)); q=L; for(int i=0;i<n;i++) { p=(LinkNode * )malloc(sizeof(LinkNode)); p->data=a[i]; q->next=p; q=p; } q->next=NULL; } void diff1(LinkNode*&A,LinkNode*&B) //第一小題函式 { LinkNode*a,*b,*a_prior,*b_prior; //a_prior,b_prior分別為遍歷迴圈中a,b節點的前驅節點 a_prior=A; int T; //輔助變數T for(a=A->next;a!=NULL;a=a->next) //遍歷A中元素 { b_prior=B; T=1; for(b=B->next;b!=NULL;b=b->next) //對A中,每一個元素都遍歷一遍B表 { if(a->data==b->data) //若兩表中出現相同元素,則刪除A,B中此元素所在節點(刪除B中節點為減少以後遍歷B表次數) { T=0; a_prior->next=a->next; //跳過a元素將a前後元素連結 free(a); a=a_prior; //∵這裡if後break跳過B迴圈後A迴圈會執行a節點前移,既下一刻開始判斷被刪除節點的下一節點 b_prior->next=b->next; //跳過b元素將b前後元素連結 free(b); b=b_prior->next; break; } b_prior=b_prior->next; } if(T) //若T==0說明原a節點已刪除,此刻a節點位置為a_prior位置,下一刻a節點前移,∴a_prior作為a節點的前驅節點此時就不必前移了 a_prior=a_prior->next; } } void diff2(LinkNode*&A,LinkNode*&B) //第二小題函式 { LinkNode*a=A->next,*b=B->next,*a_prior=A; //a_prior為a節點的前驅節點 while(a!=NULL && b!=NULL) { if(a->data > b->data) //若a節點的值大於b節點,則b節點後移 b=b->next; else if(a->data < b->data) //若a節點的值小於b節點,則a節點後移 { a_prior=a; //先將a的前驅節點前移,再將a節點前移 a=a->next; } else //若兩值相等,則刪a節點 { //b不必刪除 ∵到後面有銷燬函式銷燬b,這裡刪除b並不能像第一題一樣減少遍歷次數 a_prior->next=a->next; //跳過a元素將a前後元素連結 free(a); a=a_prior->next; } } } void main() { int A[7]={9,5,6,7,1,8,2},B[4]={8,-1,5,3}; //無序陣列,集合運算A-B應該為9,6,7,1,2 (以檢測結果) int a[10]={0,1,2,3,4,5,6,7,8,9},b[5]={2,4,6,8,10}; //有序陣列,集合運算a-b應該為0,1,3,5,7,9 LinkNode*LA=NULL,*LB=NULL; CreatList(LA,A,7); //建立無序連結串列LA,LB CreatList(LB,B,4); diff1(LA,LB); //第一題函式 DestroyList(LB); //根據題目要求釋放A和B中不需要的節點,則B連結串列全刪 DispList(LA); //最後(1)題答案即為diff1後的連結串列A,將答案輸出 DestroyList(LA); //第一題已完成,刪除原表LA,重置A,B表並開始(2)題 CreatList(LA,a,10); //建立有序表A,B CreatList(LB,b,5); diff2(LA,LB); DestroyList(LB); DispList(LA); DestroyList(LA); }