Xóa node (Delete node) trong DSLK đơn
Trong bài viết này, codehow sẽ hướng dẫn các bạn cách xóa node (Delete node) trong DSLK đơn. Đây là một thao tác thường gặp khi sử dụng danh sách liên kết đơn.
Nếu các bạn đã nắm vững kiến thức cơ bản về danh sách liên kết đơn, thì việc xóa các phần tử trở nên rất dễ dàng.
Mình sẽ hướng dẫn các bạn ba cách để xóa node khỏi DSLK đơn, đó là: Xóa node đầu, xóa node cuối và xóa node ở vị trí bất kì trong danh sách. Bây giờ chúng ta sẽ bắt đầu tìm hiểu lần lượt từng cách thôi nhé.
Xóa node ở đầu DSLK đơn
Trong trường hợp chúng ta muốn xóa node ở đầu danh sách liên kết đơn, thì cần thực hiện một số thao tác trước khi xóa node nhé.
Giả sử mình có pDel là node cần xóa, bây giờ muốn xóa pDel (node đầu tiên) ta sẽ thực hiện theo từng bước như sau:
Bước 1: Vì node cần xóa là node đầu tiên pHead, nghĩa là pDel chính là pHead. Vậy cần phải di chuyển pHead sang node kết tiếp: list.pHead = list.pHead -> pNext
Bước 2: Ngắt mối liên kết giữa pDel và node phí sau nó: pDel -> pNext = Null
.
Bước 3: Khi pDel không còn mối liên kết nào nữa, bây giờ chúng ta có thể xóa pDel được rồi: delete pDel
.
// Nếu pDel == list.pHead, tức là số cần xóa ở đầu danh sách if(pDel == list.pHead){ list.pHead = list.pHead -> pNext; pDel -> pNext = NULL; delete pDel; pDel = NULL; }
Xóa node ở cuối DSLK đơn
Việc xóa node ở cuối DSLK đơn tương tự như xóa node ở đầu DSLK đơn. Chúng ta cần di chuyển pTail về node phía trước đó, sau đó ngắt mối liên kết của pDel với ndoe trước đó. Cuối cùng là xóa pDel khi nó không còn mối liên kết với bất kì node nào nữa.
//Nếu pDel == list.pTail, tức là số cần xóa ở cuối danh sách if(pDel -> pNext == NULL){ list.pTail = pPre; pPre -> pNext = NULL; delete pDel; pDel = NULL; }
Xóa node ở vị trí bất kì trong DSLK đơn
Trong trường hợp chúng ta muốn xóa một node ở một ví trí bất kì nào đó trong danh sách. Có thể là phần tử đầu, cuối hoặc là một phần tử nằm ở vị trí bất kỳ.
Trường hợp này đặc biệt hơn rất nhiều so với hai trường hợp kia. Bởi ta cần thực hiện khá nhiều thao tác trước khi xóa, nó không đơn giản như hai trường hợp đó.
Bây giờ bắt đầu theo từng bước thôi nhé.
Bước 1: Xác định node cần xóa là pDel và node phía trước nó là pPre.
Bước 2: Thay đổi mối liên kết giữa pPre đến pTail (pPre -> pNext = pDel -> pNext) và cho pDel -> pNext = NULL.
Bước 3: Khi này pDel sẽ không còn mối liên kết đến bất kì node nào nữa, ta có thể xóa node pDel được rồi.
// và trường hợp cuối cùng số muốn xóa nằm ở giữa danh sách else{ pPre -> pNext = pDel -> pNext; pDel -> pNext = NULL; delete pDel; pDel = NULL; }
Ví dụ xóa node trong DSLK đơn.
Trong phần này, mình sẽ thực hiện một chương trình áp dụng các kiến thức cũ ở các bài viết trước. Cùng với đó là kiến thức mới ở bài viết này chính là xóa node khỏi danh sách liên kết đơn. Các bạn có thể tham khảo nhé, mình sẽ giải thích rõ trong chương trình.
#include <iostream> using namespace std; /* Khai báo giá trị data và con trỏ pNext trỏ tới phần tử kế tiếp */ struct Node { int data;// giá trị data của node Node *pNext;// con trỏ pNext }; /* Khai báo Node đầu pHead và Node cuối pTail*/ struct SingleList { Node *pHead; //Node đầu pHead Node *pTail; // Node cuối pTail }; /* khởi tạo giá trị cho Node đầu và Node cuối */ void Initialize(SingleList &list) { list.pHead=list.pTail=NULL;// khởi tạo giá trị cho Node đầu và Node cuối là Null } /* Đếm số phần tử trong danh sách */ int SizeOfList(SingleList list) { Node *pTmp=list.pHead; int nSize=0; while(pTmp!=NULL) { pTmp=pTmp->pNext; nSize++; } return nSize; } /* tạo Node trong danh sách liên kết đơn */ Node *CreateNode(int d) { Node *pNode=new Node; //sử dụng pNode để tạo một Node mới if(pNode!=NULL) // Nếu pNode != Null, tức là pNode có giá trị thì { pNode->data=d; // gán giá trị data cho d pNode->pNext=NULL;// và cho con trỏ pNext trỏ tới giá trị Null } else // Nếu pNode == Null, tức là pNode không có giá trị thì xuất thông tin { cout<<"Error allocated memory"; } return pNode;//trả về pNode } /* chèn Node đầu danh sách */ void InsertFirst(SingleList &list,int d) { Node *pNode=CreateNode(d); if(list.pHead==NULL) { list.pHead=list.pTail=pNode; } else { pNode->pNext=list.pHead; list.pHead=pNode; } } /* chèn node vào cuối danh sách */ void InsertLast(SingleList &list,int d) { Node *pNode=CreateNode(d); if(list.pTail==NULL) { list.pHead=list.pTail=pNode; } else { list.pTail->pNext=pNode; list.pTail=pNode; } } /* chèn node vào giữa danh sách */ void InsertMid(SingleList &list, int pos, int d){ // Nếu pos < 0 hoặc pos lớn hơn kích thước của danh sách thì reuturn if(pos < 0 || pos >= SizeOfList(list)){ cout<<"Không thể chèn Node!!!"; return; } // Nếu pos == 0 thì gọi hàm InsertFirst if(pos == 0){ InsertFirst(list, d); } //Nếu pos == SizeOfList - 1 thì gọi hàm InsertLast else if(pos == SizeOfList(list)-1){ InsertLast(list, d); } //Ngược lại thì thay đổi mối liên kết giữa các phần tử, cụ thể: else{ Node *pNode = CreateNode(d); Node *pIns = list.pHead; Node *pPre = NULL; int i = 0; //thực hiện vòng lặp tìm pPre và pIns while(pIns != NULL){ if(i == pos) break; pPre = pIns; pIns = pIns ->pNext; i++; } //sau khi tìm được thì thay đổi con trỏ pNext pPre ->pNext=pNode; pNode->pNext=pIns; } } /* xóa node khỏi danh sách liên kết */ void RemoveNode(SingleList &list, int d){ Node *pDel = list.pHead; // tạo một node pDel để xóa //Nếu pDel == Null thì danh sách rỗng if(pDel == NULL){ cout<<"Danh sách rỗng!!"; } //ngược lại thì xét điều kiện else{ Node *pPre = NULL; //dùng vòng lặp while để tìm ra pDel và pPre (vị trí đứng trước pDel) while(pDel != NULL){ if(pDel -> data == d){ break; } pPre = pDel; pDel = pDel -> pNext; } //Nếu pDel == null tức là không tìm thấy số cần xóa if(pDel == NULL){ cout<<"Không tìm thấy số cần xóa"; } // Ngược lại tiếp tục xét điều kiện else{ // Nếu pDel == list.pHead, tức là số cần xóa ở đầu danh sách if(pDel == list.pHead){ list.pHead = list.pHead -> pNext; pDel -> pNext = NULL; delete pDel; pDel = NULL; } //Nếu pDel == list.pTail, tức là số cần xóa ở cuối danh sách else if(pDel -> pNext == NULL){ list.pTail = pPre; pPre -> pNext = NULL; delete pDel; pDel = NULL; } // và trường hợp cuối cùng số muốn xóa nằm ở giữa danh sách else{ pPre -> pNext = pDel -> pNext; pDel -> pNext = NULL; delete pDel; pDel = NULL; } } } } /* hàm xuất dữ liệu */ void PrintList(SingleList list) { Node *pTmp=list.pHead; if(pTmp==NULL) { cout<<"Danh sách rỗng!"; return; } while(pTmp!=NULL) { cout<<pTmp->data<<" "; pTmp=pTmp->pNext; } } int main() { SingleList list; Initialize(list); //Thêm node đầu danh sách InsertFirst(list, 5); InsertFirst(list, 7); InsertFirst(list, 3); cout<<"Các Node 5, 7, 3 trong danh sách sau khi InsertFirst là: \n"; PrintList(list); //Thêm node cuối danh sách InsertLast(list, 4); InsertLast(list, 2); InsertLast(list, 6); cout<<"\nCác Node 4, 2, 6 trong danh sách sau khi InsertLast là: \n"; PrintList(list); //Thêm node giữa danh sách InsertMid(list, 4, 11); InsertMid(list, 2, 12); InsertMid(list, 3, 13); cout<<"\nCác Node 11, 12, 13 sau khi chèn vào vị trí 4, 2, 3 là: \n"; PrintList(list); //Xóa node khỏi danh sách RemoveNode(list, 3); RemoveNode(list, 11); RemoveNode(list, 6); cout<<"\nDanh sách sau khi xóa các node 3, 11, 6 là: \n"; PrintList(list); cout<<"\n-------------------------------------\n"; cout<<"Chương trình này được đăng tại codehow.net"; }
Kết quả:
Như vậy là chúng ta đã cùng nhau tìm hiểu về cách xóa node trong DSLK đơn. Ở bài viết tiếp theo mình sẽ hướng dẫn các bạn cách tìm kiếm và sắp xếp trong danh sách liên kết đơn. Các bạn chú ý theo dõi nhé, cảm ơn các bạn rất nhiều !!!