題目來自某NJU同學的程序設計基礎作業
貼一下題目:

用鏈表建立兩個整數集合A和B(從鍵盤鍵入集合的元素,以-1結束,集合中沒有-1)。
分別編寫三個函數計算這兩個集合的。
a.交集
b.並集
c.差集A-B
三個函數的計算結果為新的鏈表。
輸出這三個新鏈表。
做題心得
其實這道題用數組直接能秒殺掉,難度就在對於單鏈表的理解與應用。對指針和結構體有挺高的掌握要求。
之前沒好好學鏈表,總覺得數組能解決的事用數組,數組解決不了的用STL(stl永遠的神不接受反駁)
補了三天的鏈表,總算學得明白了一點,簡單把題過了一下。沒有用函數分段,其實分段一下很簡單。
P.S肥腸感謝雞哥龍神的鼎力相助!
直接po代碼,有錯誤或者其他更好的思路也希望dalao們可以帶帶
#include<stdio.h> #include<stdlib.h> struct node//鏈表結構體 { int data;//數據域 struct node* next;//指向下一個結構體的指針 }; node* create(int data)//新建鏈表項(新結構體) { node* newNode = (node*)malloc(sizeof(node));//給這個結構體開空間 newNode->data = data;//保存數據 newNode->next = NULL;//指針為空 return newNode;//返回新建的結構體 } int main() { struct node *p,*q,*t,*h;//定義幾個臨時變量,會用到 int tmp; //輸入集合A scanf("%d", &tmp); struct node* head_a = create(tmp);//頭節點 p = head_a;//p是臨時變量 while (scanf("%d", &tmp) && tmp != -1)//輸入數字,且當tmp=-1的時候結束 { struct node* a = create(tmp);//給鏈表A新建節點 p->next = a;//上一個節點的指針指向現在這個 p = a;//臨時變量變成現在這個 } //輸入集合A scanf("%d", &tmp); struct node* head_b = create(tmp);//頭節點 p = head_b;//p是臨時變量 while (scanf("%d", &tmp) && tmp != -1)//輸入數字,且當tmp=-1的時候結束 { struct node* b = create(tmp);//給鏈表A新建節點 p->next = b;//上一個節點的指針指向現在這個 p = b;//臨時變量變成現在這個 } struct node* head_jiao = create(-1);//定義交集的頭結點 struct node* head_bing = create(-1);//定義並集的頭結點 struct node* head_cha = create(-1);//定義差集的頭結點 /* 交集思路: 遍歷A,對A的每個元素 ,都與B中的元素進行一一對比 類似於for循環中的 for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { 比較a和b } } */ p=head_a;//p是臨時變量,從A的頭開始 t=head_jiao;//t是臨時變量,用來存交集的鏈表 while(p!=NULL)//鏈表A非空 ,遍歷A鏈表 { q=head_b;//q是臨時變量 ,從B的頭開始 while(q!=NULL)//鏈表B非空 ,遍歷B鏈表 { if(q->data==p->data)//B元素=A元素 { //如果a和b中有相同元素,則存進交集鏈表中 //以下操作與輸入A,B集合同原理 struct node* jiao = create(p->data); t->next = jiao; t = jiao; break;//因為找到了,所以break掉,去比較A的下一個元素 } q=q->next;//鏈表B的當前位置后移(q->next是下一個元素,讓q=下一個元素 } p=p->next;//鏈表A的當前位置后移(p->next是下一個元素,讓p=下一個元素 } /* 輸出交集 因為head_jiao->data頭節點的數據域中存的是-1(見上文定義交集頭結點 故從head_jiao的下一個開始 */ t=head_jiao->next; while(t!=NULL)//遍歷交集鏈表 { printf("%d ",t->data);//輸出元素,記得加空格 t=t->next;//后移 } //Attention:這個-1不應該被放在鏈表中 printf("-1\n");//最后的元素以-1結尾,記得加換行 /* 並集思路: 先復制A的所有元素在並集bing里面 然后遍歷B,將B的每一個元素都與bing中元素比較 若比較到最后都不一樣,則當前元素不在bing中 將這個元素添加進bing的末尾 */ p=head_a;//p是臨時變量,從A的頭開始 t=head_bing;//t是臨時變量,用來存並集的鏈表 while(p!=NULL)//遍歷鏈表A { //以下操作與輸入A,B集合同理,使用鏈表A的數據 struct node* bing = create(p->data); t->next = bing; t = bing; p=p->next;//鏈表A的當前位置后移(p->next是下一個元素,讓p=下一個元素 } q=head_b;//q是臨時變量,從B的頭開始 while(q!=NULL)//遍歷鏈表B { h=head_bing;//h是臨時變量,讀取並集的鏈表 int flag=0;//用flag來記錄是否有相同元素 while(h!=NULL)//遍歷並集 { if(h->data==q->data)//存在相同元素 { flag=1; break; } h=h->next;//后移 } if(!flag)//如果不存在相同元素 { //以下操作與輸入A,B集合同理,使用鏈表B的當前元素數據 //t還是上面復制的時候定義的那個,繼續相同操作 struct node* bing = create(q->data); t->next = bing; t = bing; } q=q->next;//后移 } /* 輸出並集 因為head_bing->data頭節點的數據域中存的是-1(見上文定義並集頭結點 故從head_bing的下一個開始 */ t=head_bing->next; while(t!=NULL)//遍歷並集鏈表 { printf("%d ",t->data);//輸出元素,記得加空格 t=t->next;//后移 } //Attention:這個-1不應該被放在鏈表中 printf("-1\n");//最后的元素以-1結尾,記得加換行 /* 差集思路: 同並集,先復制鏈表A在鏈表cha里面 再遍歷鏈表bing,如果遇到元素在鏈表A中,則刪除鏈表節點 */ p=head_a;//p是臨時變量,從A的頭開始 t=head_cha;//t是臨時變量,用來存差集的鏈表 while(p!=NULL)//遍歷鏈表A { //以下操作與輸入A,B集合同理,使用鏈表A的數據 struct node* cha = create(p->data); t->next = cha; t = cha; p=p->next;//鏈表A的當前位置后移(p->next是下一個元素,讓p=下一個元素 } q=head_jiao;//q是臨時變量,從jiao的頭開始 while(q!=NULL)//遍歷鏈表jiao { h=head_cha;//h是臨時變量,從cha的第1個開始 t=head_cha->next;//t是臨時變量,從cha的第2個開始 while(t!=NULL)//遍歷cha差集,尋找當前數,然后把它刪了 { if(t->data==q->data)//如果相等,刪除 { h->next=t->next;//跳過t指向下一個 break; } //如果沒刪除,后移 h=h->next; t=t->next; } q=q->next;//后移 } /* 輸出差集 因為head_cha->data頭節點的數據域中存的是-1(見上文定義並集頭結點 故從head_cha的下一個開始 */ t=head_cha->next; while(t!=NULL)//遍歷差集鏈表 { printf("%d ",t->data);//輸出元素,記得加空格 t=t->next;//后移 } //Attention:這個-1不應該被放在鏈表中 printf("-1\n");//最后的元素以-1結尾,記得加換行 return 0; }
