LATEST

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

bai28 01 png

Bước 2: Ngắt mối liên kết giữa pDel và node phí sau nó: pDel -> pNext = Null.

bai28 02 png

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.

bai28 03 png

// 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.

bai28 04 png

//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.

bai28 05 png

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.

bai28 06 png

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ả:

bai28 07 png

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 !!!

Cùng chuyên mục:

Xóa node khỏi cây nhị phân tìm kiếm

Xóa node khỏi cây nhị phân tìm kiếm

Tìm node Max và Min trong cây nhị phân tìm kiếm

Tìm node Max và Min trong cây nhị phân tìm kiếm

Xuất node con và node lá trong cây nhị phân tìm kiếm

Xuất node con và node lá trong cây nhị phân tìm kiếm

Tìm kiếm trên cây nhị phân tìm kiếm

Tìm kiếm trên cây nhị phân tìm kiếm

Duyệt cây nhị phân tìm kiếm

Duyệt cây nhị phân tìm kiếm

Thêm node vào cây nhị phân tìm kiếm

Thêm node vào cây nhị phân tìm kiếm

Cây nhị phân (Binary tree) là gì? Cơ chế hoạt động của nó

Cây nhị phân (Binary tree) là gì? Cơ chế hoạt động của nó

Cách gộp hai danh sách liên kết đôi

Cách gộp hai danh sách liên kết đôi

Tìm kiếm phần tử trong DSLK đôi

Tìm kiếm phần tử trong DSLK đôi

Xóa node trong DSLK đôi

Xóa node trong DSLK đôi

Chèn node (Insert node) vào DSLK đôi

Chèn node (Insert node) vào DSLK đôi

Duyệt danh sách liên kết đôi

Duyệt danh sách liên kết đôi

Tạo node mới trong DSLK đôi

Tạo node mới trong DSLK đôi

DSLK đôi là gì? Cấu trúc dữ liệu của DSLK đôi

DSLK đôi là gì? Cấu trúc dữ liệu của DSLK đôi

Quản lý sinh viên bằng DSLK đơn

Quản lý sinh viên bằng DSLK đơn

Tìm kiếm và sắp xếp trong DSLK đơn

Tìm kiếm và sắp xếp trong DSLK đơn

Chèn node (Insert node) vào DSLK đơn

Chèn node (Insert node) vào DSLK đơn

Tạo node mới trong DSLK đơn

Tạo node mới trong DSLK đơn

Cấu trúc dữ liệu của DSLK đơn

Cấu trúc dữ liệu của DSLK đơn

Danh sách liên kết (Linked List) là gì? Các loại danh sách liên kết

Danh sách liên kết (Linked List) là gì? Các loại danh sách liên kết

Top