Chèn node (Insert node) vào DSLK đơn
Trong bài viết này, codehow sẽ hướng dẫn các bạn cách chèn node (Insert node) vào DSLK đơn. Hiểu đơn giản hơn thì việc này chính là thêm một phần tử vào trong DSLK đơn.
Trước khi bắt đầu vào bài học này, phải chẵn chắn rằng các bạn đã xem hai bài viết trước đó là: Cấu trúc dữ liệu DSLK đơn và cách tạo node mới trong DSLK đơn nhé. Vì đây là nền tảng để các bạn có thể thực hiện thao tác thêm node vào trong DSLK đơn.
Chúng ta sẽ tìm hiểu ba cách để thêm node (Insert node) vào trong DSLK đơn đó là: Thêm vào đầu danh sách, thêm vào cuối danh sách và thêm vào giữa danh sách.
Bây giờ các bạn cùng mình đi tìm hiểu từng cách một nhé, sau đó mình sẽ đưa ra ví dụ cụ thể cho các bạn tham khảo.
Chèn node vào đầu DSLK đơn
Để có thể chèn được node vào DSLK đơn, các bạn phải đảm bảo rằng đã cài đặt DSLK đơn và khai báo, khởi tạo node đã nhé.
Dưới đây là hàm chèn node vào đầu DSLK đơn, các bạn hãy xem đã nhé, sau đó mình giải thích ngay bên dưới.
/* chèn Node đầu danh sách */ void InsertFirst(SingleList &list,int d) { Node *pNode=CreateNode(d); //tạo một node mới //Nếu pHead == null thì pNode chính là pHead if(list.pHead==NULL) { list.pHead=list.pTail=pNode; } // Ngược lại ta phải chèn pNode vào pHead sau đó đưa pHead ra đầu danh sách else { pNode->pNext=list.pHead; list.pHead=pNode; } }
Giải thích:
Như các bạn đã biết thì một node khi được khỏi tạo sẽ có giá trị data và con trỏ pNext -> NULL
. Như vậy nếu pHead == NULL
nghĩa là khi thêm vào đó là phần tử đầu tiên. Nếu pHead != NULL
thì ta thay đổi con trỏ trỏ từ pNext -> pHead
.
//Nếu pHead == null thì pNode chính là pHead if(list.pHead==NULL) { list.pHead=list.pTail=pNode; }
Bởi vì pHead luôn luôn quản lý node đầu tiên, vậy nên sau khi trỏ đến pHead, ta cần đưa pHead về đầu danh sách: pHead -> pNode
.
// Ngược lại ta phải chèn pNode vào pHead sau đó đưa pHead ra đầu danh sách else { pNode->pNext=list.pHead; list.pHead=pNode; }
Chèn node vào cuối DSLK đơn
Việc chèn node vào cuối DSLK đơn được thực hiện tương tự việc chèn node vào đầu DSLK đơn. Các bạn hãy xem hàm chèn node vào cuối DSLK đơn, sau đó mình sẽ giải thích rõ ngay bên dưới.
/* chèn node vào cuối danh sách */ void InsertLast(SingleList &list,int d) { Node *pNode=CreateNode(d); // tạo node mới // Nếu pTail == null thì pNode chính là pTail if(list.pTail==NULL) { list.pHead=list.pTail=pNode; } // Ngược lại nếu pTail != null thì chèn pNode vào pTail và đưa pTail ra cuối danh sách else { list.pTail->pNext=pNode; list.pTail=pNode; } }
Giải thích:
Đầu tiên ta kiểm tra xem nếu pTail == NULL
, nghĩa là node thêm vào chính là node cuối cùng, khi đó chúng ta không cần thay đổi con trỏ pNext.
// Nếu pTail == null thì pNode chính là pTail if(list.pTail==NULL) { list.pHead=list.pTail=pNode; }
Nếu pTail != NULL
, nghĩa là node thêm vào không phải node cuối. Khi đó ta cần thay đổi con trỏ pNext để node thêm vào chính là node cuối cùng. Sau khi thay đổi con trỏ pNext, ta cần đưa pTail về cuối danh sách, bởi vì nó luôn luôn quản lý node cuối trong danh sách.
// Ngược lại nếu pTail != null thì chèn pNode vào pTail và đưa pTail ra cuối danh sách else { list.pTail->pNext=pNode; list.pTail=pNode; }
Chèn node vào giữa DSLK đơn
Chèn node vào giữa DSLK đơn nghĩa là chèn vào một vị trí bất kì nằm giữa DSLK đơn. Khi đó ta cần thêm các con trỏ,biến và hàm sau đây:
- pPre là node đứng trước node cần chèn.
- pIsn là node đứng sau node cần chèn.
- Tham số pos là vị trí cần chèn.
- Tham số d là giá trị cần chèn.
- Hàm SizeOfList() để lấy kích thước của danh sách.
Các bạn hãy xem hàm chèn node vào giữa DSLK đơn dưới đây. Đầu tiên là hàm SizeOfLIst()
để lấy kích thước, sau đó là hàm InsertMid()
để chèn node vào giữa DSLK đơn.
/* Đế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; }
/* 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; } }
Giải thích:
Đầu tiên chúng ta cần kiểm tra xem nếu vị trí chèn pos lớn hơn kích thước của danh sách thì thông báo không thể chèn.
// 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; }
Kiểm tra xem nếu vị trí cần chèn là vị trí đầu thì gọi hàm InsertFirst()
, nếu là vị trí cuối thì gọi hàm InsertLast()
.
// 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); }
Còn lại các trường hợp khác thì chúng ta chỉ cần thay đổi mối liên kết của node là xong.
pPre ->pNext=pNode; pNode->pNext=pIns;
Ví dụ chèn node vào DSLK đơn trong C / C++
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 đã học nhé. Chương trình sẽ thực hiện cài đặt cấu trúc dữ liệu của DSLK đơn, tạo node và chèn node. Mình sẽ thực hiện cả ba cách chèn node để các bạn có thể tham khảo.
/* 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; } } /* hàm xuất dữ liệu */ void PrintList(SingleList list) { Node *pTmp=list.pHead; if(pTmp==NULL) { cout<<"The list is empty!"; 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 Insert vào vị trí 4, 2, 3 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ác cách chèn node (Insert node) vào DSLK đơn. Ở bài viết tiếp theo mình sẽ hướng dẫn các bạn cách xóa node trong DSLK đơn. Các bạn chú ý theo dõi nhé, cảm ơn các bạn rất nhiều.