鏈表交集、合並、排序
阿新 • • 發佈:2019-03-23
ext break bsp 重復元素 鏈表合並 順序 操作 存儲 lis
第四周
要求:
1、將兩個有序的遞增鏈表合並為一個遞增的有序鏈表。要求結果鏈表仍使用原來兩個鏈表的儲存空間,不另外占用其他的儲存空間。表中不允許有重復數據。
2、已知兩個鏈表A和B分別表示兩個集合,其元素遞增排列。設計一個算法用於求出A與B的交集,並存放在A鏈表中。
思路:首先就是創建鏈表。一般有前插法和後插法;二 要求遞增的話可以用一個排序算法(簡單看了一下冒泡排序)。三 鏈表顯示和銷毀函數。
四 重點就是合並和交集函數。註意就是對鏈表操作要釋放多余的存儲空間,比如:頭結點,重復元素結點等
先定義結構
typedef struct LNode//定義結構 {int data; struct LNode *next; }LNode, *Head;
一、創建鏈表(後插法)
Head Create(void)//創建鏈表 { LNode *head, *r, *p; head = new LNode; if (head == NULL) cout << "頭結點創建失敗!\n"; p = head; int x, cycle = 1; while (cycle) { cout << "輸入一個整數.\n"; cin>> x; if (x != 0) { r = new LNode; r->data = x; p->next = r; p = r; } else { cycle = 0; } } p->next = NULL; cout << "鏈表創建成功!\n"; return head; }
二、排序(遞增)
Head Order(Head head)//鏈表節點排序 { LNode *p = head->next, *q = head->next; if (!p) return head; int i = 0, temp = 0, flag = 1; while (q) { q = q->next; ++i;//數據節點個數i } while (flag && i >= 0) {//冒泡排序 flag = 0; while (p->next != NULL) { if (p->data > p->next->data) { temp = p->data; p->data = p->next->data; p->next->data = temp; flag = 1;//標誌置為1表示本輪有交換 } p = p->next; } --i; p = head->next;//重新指向首元結點為下輪準備 } return head; }
三、鏈表顯示
Status print(Head head) { int i = 0; LNode *p = head; while (!p) return OK; while (p->next != NULL) { p = p->next; cout << p->data; cout << " "; ++i; } cout << " 共有"<<i<<"個元素\n"; return OK; }
四、銷毀鏈表
Status DestroyList(Head head) { LNode *p; while (head->next != NULL) { p = head; head = head->next; delete p; } delete head; return OK; }
五、鏈表交集
交集AB鏈表放入A鏈表中,釋放B鏈表;head1為A鏈表,head2為B鏈表。
Head Intersection(Head head1, Head head2)//交集放入A鏈表 { LNode *head = NULL, *p1 = NULL, *p2 = NULL, *p = NULL; head = head1; //交集為空 while (head1->next==NULL || head2->next==NULL) { while (head2->next != NULL)//A為空鏈表 直接刪除B鏈表 { p = head2; head2 = head2->next; delete p; } delete head2; return head1; break; } LNode *move = head, *temp = NULL; p1 = head1->next; p2 = head2->next; delete head2; //AB均不為空 while (p1&&p2->next != NULL){ if (p1->data < p2->data) p1 = p1->next; else if (p1->data > p2->data) p2 = p2->next; else if (p1->data == p2->data) { move->next = p1; move = p1; p1 = p1->next; } } if (p2->next == NULL) {//判斷B鏈表最後一個結點 if (p1->data == p2->data) { move->next = p1; move = p1; p1 = p1->next; } } move->next = NULL;//尾部指針為NULL return head; }
六、鏈表合並
這裏AB合並後放入B鏈表中。
Head Combine(Head head1, Head head2)//合並後放入B鏈表 { LNode *head=head2, *p1=NULL, *p2=NULL; if (head1->next==NULL) {//A為空鏈表或者AB都為空 delete head1; return head2; } else if (head2->next == NULL) {//B為空鏈表 head2->next = head1->next;//A鏈表賦給B鏈表 delete head1; return head2; } p1 = head1->next; p2 = head2->next; delete head1; LNode *move = head, *temp = NULL; //按遞增順序依次鏈接 while (p1&&p2) { if (p1->data < p2->data) { move->next = p1; move = p1; p1 = p1->next; } else if (p1->data > p2->data) { move->next = p2; move = p2; p2 = p2->next; } else if(p1->data == p2->data) {//相同數據只保存一個,p1p2向後移一位 temp = p2; move->next = p1; move = p1; p1 = p1->next; p2 = p2->next; delete temp;//刪除p2相同結點 } } if (p1)//p2為NULL,直接連接p1後面的結點 move->next = p1; if (p2)//p1為NULL,直接連接p2後面的結點 move->next = p2; return head; }
測試
int main() { cout << "創建一個鏈表A. 輸入0結束\n"; Head head1 = Create(); cout << "創建一個鏈表B. 輸入0結束\n"; Head head2 = Create(); char ch; while (1) { cout << "---------------------------------------------------------------------------\n"; cout << "+請選擇要進行的操作:<a>顯示A <b>顯示B <c>交集AB <d>合並AB <x>退出+\n"; cout << "---------------------------------------------------------------------------\n"; ch = _getwch(); if (ch == ‘a‘) { cout << "A鏈表:"; print(Order(head1)); } else if (ch == ‘b‘) { cout << "B鏈表:"; print(Order(head2)); } else if (ch == ‘c‘) { cout << "AB交集為:"; print(Order(Intersection(head1, head2))); cout << "輸入任意字符結束\n"; ch = _getwch(); DestroyList(head1); break; } if (ch == ‘d‘) { cout << "AB合並為:"; print(Order(Combine(head1, head2))); cout << "輸入任意字符結束\n"; ch = _getwch(); DestroyList(head2); break; } else if (ch == ‘x‘) { break; } } }
運行結果:
交集:
合並:
鏈表交集、合並、排序