任務描述
刪除鏈表的結點時,有時候不知道結點在哪,只知道結點數據的特征,如刪除成績低於60
的學生結點、刪除學號為20160903
的學生等。本關要求按照數據輸入的順序構建一個線性表,然后輸入待刪除節點數據信息,在鏈表中查找符合該信息的節點,並刪除;若不存在符合該數據信息的節點,則不操作。
編程要求
本關的編程任務是補全step5/deletehas.h
文件中deletehas
函數,以實現刪除線性表指定位置結點的要求。 // 函數deleteHas:刪除鏈表中data域為x的第一個節點,若不存在該節點,則操作 // 參數:h-鏈表頭指針,x-結點包含的數據 // 返回值:刪除結束后鏈表首結點地址 node * deleteHas(node * h, int x);
相關知識
程序可以分為兩步: 1、利用循環順序查找值為x的節點的**前驅節點**,並用指針P指向該前驅節點,若不存在值為x的節點,則前驅節點指針P為空; 2、前驅節點指針P不為空,則刪除值P指針指向的節點的后繼節點,刪除時注意釋放節點空間。
評測說明
本關中包含三個文件分別是: step5/deleteHas.h :此文件為學員文件,包含尾插法構建鏈表的函數實現。 step5/linkList.h:此文件包含鏈表常見操作的說明與實現,引用了deleteHas.h step5/test.cpp:此文件為評測文件(含main函數),引用“linkList.h”。 (上述三個文件可通過點擊在代碼取的右上角文件夾中的step5文件夾中查看) (注意:本關所實現鏈式線性表為帶頭結點的單鏈表) 以下是平台對step5/test.cpp
的樣例測試集:
輸入輸出說明
輸入n(1<=n<=100),然后輸入n個整數,最后輸入待刪除元素x,按元素輸入書順序刪除首個x元素(若不存在則不刪除),輸出剩余元素,如下所示:(注意:鏈表的輸出函數已經實現,詳情請閱讀step5文件夾中的文件。)
測試輸入: 5
2 3 8 5 1
2
預期輸出: List: 3 8 5 1
測試輸入: 6
9 8 7 6 5 4
6
預期輸出: List: 9 8 7 5 4
test.cpp
#include "linkList.h" int main() { int n, i, num; node* t; node* head = new node;// 帶頭結點單鏈表,頭結點指針head head->next = NULL; // 頭結點head->next==NULL,鏈表為空 //輸入結點數 cin >> n; for (i = 0; i < n; i++) { //為新節點動態分配空間 t = new node; cin >> t->data; //輸入結點數據 t->next = NULL; //結點指針域值為空 //按輸入順序構建鏈表 head = insertTail(head, t); } //輸入要刪除結點包含的數據 cin >> num; //刪除包含num的結點 head = deleteHas(head, num); //輸出鏈表 printList(head); //刪除結點,釋放空間 delList(head); return 0; }
linkList.h
#include <iostream> using namespace std; // 定義結點結構 struct node { int data; // 數據域 node* next; // 指針域,指向下一個結點 }; // 函數deleteHas:刪除鏈表中data為x的結點,如果有多個這樣的結點,只刪除第一個,若不存在data為x的節點,則不操作 // 參數:h-鏈表頭指針,n-結點包含的數據 // 返回值:刪除結束后鏈表首結點地址 node* deleteHas(node* h, int x); // 函數insertTail:鏈表尾部插入 // 參數:h-鏈表頭指針,t-指向要插入的結點 // 返回值:插入結點后鏈表的頭結點地址 node* insertTail(node* h, node* t); // 函數printList:輸出鏈表,每個數據之間用一個空格隔開 // 參數:h-鏈表頭指針 void printList(node* h); // 函數delList:刪除鏈表,釋放空間 // 參數:h-鏈表頭指針 void delList(node* h); #include "deleteHas.h" //函數delList:刪除鏈表,釋放空間 //參數:h-鏈表頭指針 void delList(node* h) { node* p = h; //指針p指向頭結點,第一個要刪除的結點 while (p) //這個結點是存在的 { h = h->next; //頭指針h指向下一個結點(下一個結點的地址存在當前結點的指針域中,即h->next中 delete p; //刪除p指向的結點 p = h; //p指向當前的頭結點,即下一個要刪除的結點 } } //函數printList:輸出鏈表,每個數據之間用一個空格隔開 //參數:h-鏈表頭指針 void printList(node* h) { cout << "List:"; h = h->next; while (h) {// h為真,即h指向的結點存在,則輸出該結點的數據 cout << " " << h->data; // 輸出結點數據 h = h->next; // 將該結點的指針域賦值給h,h就指向了下一個結點 } cout << endl; // 輸出換行符 } node* insertTail(node* h, node* t) { // 請在此添加代碼,補全函數insertTail /********** Begin *********/ node* p = h; // 讓p指向最后一個結點 while (p->next) p = p->next; p->next = t; // 讓最后一個結點的指針域指向結點t t->next = NULL; // 鏈表尾指針置為NULL return h; // 返回第一個結點的地址(即鏈表頭指針) /********** End **********/ }
deleteHas.h
// 函數deleteHas:刪除鏈表中data為x的結點,如果有多個這樣的結點,只刪除第一個 // 參數:h-鏈表頭指針,n-結點包含的數據 // 返回值:刪除結束后鏈表首結點地址 node* deleteHas(node* h, int n) { // 請在此添加代碼,補全函數deleteHas /********** Begin *********/ node *p = NULL, *q = h; // p為要刪除結點的前結點,q指向要刪除結點 while(q) {// h為真,即h指向的結點存在 if(q->data == n) break; // 找到了 if(q->next == NULL) // 后面沒有結點了,沒有結點滿足條件 return h; // 不刪除,直接返回 // 繼續往后找,兩個指針一起后移 p = q; q = q->next; } // 刪除q指向的結點 if(p == NULL) // 刪除頭結點 { h = q->next; // 下一個結點變成頭結點 delete q; // 刪除結點 return h; } // 不是頭結點 p->next = q->next; // 把q指向結點的指針域(q后面結點的地址)賦值給p指向結點的指針域 return h; /********** End **********/ }