LATEST

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

Trong bài viết này, codehow sẽ hướng dẫn các bạn cách chèn node vào DSLK đôi trong C / C++. Đây là một thao tác rất quan trọng, bởi có nó thì DSLK đôi của chúng ta mới có dữ liệu để thực hiện các thao tác khác.

Tương tự như DSLK đơn, chúng ta có hai cách để chèn node vào DSLK đôi, đó là:

  • Chèn node vào đầu DSLK đôi.
  • Chèn node vào cuối DSLK đôi.

Bây giờ chúng ta sẽ bắt đầu tìm hiểu từng cách thôi nhé. Sau đó mình sẽ thực hiện một chương trình áp dụng các kiến thức ở bài trước cũng như kiến thức ở bài này cho các bạn tham khảo nhé.

Chèn node vào đầu DSLK đôi

Nếu các bạn đã tìm hiểu về cách chèn node vào DSLK đơn ở bài trước mình giới thiệu, thì đối với DSLK đôi cũng tương tự nhé.

bai34 0 png

Dưới đây là hàm chèn node vào đầu DSLK đôi, các bạn xem trước rồi sau đó mình sẽ giải thích ngay bên dưới nhé. Lưu ý rằng chúng ta cần tạo các cấu trúc dữ liệu của DSLK đơn rồi mới thực hiện được thao tác chèn.

/* thêm node vào đầu danh sách */
void InsertAtHead(int x) {
  //sử dụng hàm tạo Node tạo một Node mới
    struct Node* newNode = CreateNode(x);
   //nếu danh sách rỗng thì node chèn vào vừa là node đầu vừa là node cuối
    if(head == NULL) {
        head = newNode;
        tail = newNode;
        return;
    }
    //Nếu danh sách không rỗng thì, dịch chuyển Node head về node mới chèn, và cho con trỏ của newNode trỏ đến Node head
    head->prev = newNode;
    newNode->next = head;
    head = newNode;
}

Giải thích:

  • Đầu tiên chúng ta tạo mới một node bằng cách sử dụng hàm CreateNote().
  • Tiếp đến ta xét điều kiện nếu danh sách rỗng thì node vừa mới tạo chính là node đầu cũng như là node cuối.
  • Nếu trong danh sách đã tồn tại phần tử, thì ta thực hiện chèn vào đầu danh sách:
    • Dịch chuyển node đầu về NewNode.

Chèn node vào cuối DSLK đôi

Cách chèn node vào cuối DSLK đôi là cách thường dùng nhất. Ví dụ khi chúng ta chèn phần tử vào mảng, thì ta cũng thường chèn vào cuối mảng.

bai34 01 png

Đầu tiên ta cũng tạo mới node NewNode bằng cách sử dụng hàm CreateNode().

Sau đó kiểm tra xem danh sách có rỗng hay không. Nếu rỗng thì NewNode chính là node đầu cũng như là node cuối.

Ngược lại nếu danh sách tồn tại phần tử thì ta chèn node vào cuối danh sách bằng cách:

  • Thiết lập con trỏ next của node tail trỏ đến NewNode.
  • Thiết lập con trỏ pre của NewNode trỏ đến node tail.
  • Dịch chuyển tail về NewNode.

Như vậy là chúng ta đã chèn xong một node vào cuối DSLK đôi. Dưới đây là hàm mình đã viết sẵn, các bạn có thể tham khảo nhé.

/* thêm node vào cuối danh sách */
void InsertLast(int x) {
  //sử dụng hàm tạo Node để tạo node mới newNode
    struct Node* newNode = CreateNode(x);
    //Nếu danh sách rỗng thì newNode vừa là node đầu vừa là node cuối
    if(head == NULL) {
        head = newNode;
        tail = newNode;
        return;
    }
    //Nếu danh sách có phần tử thì, 
    tail->next = newNode;// con trỏ next của tail trỏ đến newNode
    newNode->prev = tail;// con trỏ prev của newNode trỏ đến tail
    tail = newNode;//dịch chuyển tail về newNode, vì tail luôn luôn quản lý phần tử cuối cùng trong danh sách
}

Ví dụ chèn node vào DSLK đôi

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 ở các bài trước, cùng với đó là kiến thức ở bài học này. Cụ thể như sau:

  • Tạo cấu trúc dữ liệu của DSLK đôi.
  • Chèn node vào đầu danh sách liên kết đôi.
  • Chèn node vào cuối danh sách liên kết đôi.
  • Duyệt danh sách liên kết đôi từ đầu về cuối và từ cuối về đầu.

Bây giờ chúng ta sẽ bắt đầu thực hiện từng yêu cầu một nhé.

Bước 1: Tạo cấu trúc dữ liệu của DSLK đôi.

using namespace std;
/* tạo cấu trúc node */
struct Node  {
    int data;
    struct Node* next;
    struct Node* prev;
};
 
struct Node *head, *tail; // Khởi tạo Node head global của dslk đôi.
  
/* tạo node mới */
struct Node* CreateNode(int x) {
    struct Node* newNode
        = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = x;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}

Bước 2: Chèn node vào đầu DSLK đôi.

/* thêm node vào đầu danh sách */
void InsertFirst(int x) {
  //sử dụng hàm tạo Node tạo một Node mới
    struct Node* newNode = CreateNode(x);
   //nếu danh sách rỗng thì node chèn vào vừa là node đầu vừa là node cuối
    if(head == NULL) {
        head = newNode;
        tail = newNode;
        return;
    }
    //Nếu danh sách không rỗng thì, dịch chuyển Node head về node mới chèn, và cho con trỏ của newNode trỏ đến Node head
    head->prev = newNode;
    newNode->next = head;
    head = newNode;
}

Bước 3: Chèn node vào cuối DSLK đôi.

/* thêm node vào cuối danh sách */
void InsertLast(int x) {
  //sử dụng hàm tạo Node để tạo node mới newNode
    struct Node* newNode = CreateNode(x);
    //Nếu danh sách rỗng thì newNode vừa là node đầu vừa là node cuối
    if(head == NULL) {
        head = newNode;
        tail = newNode;
        return;
    }
    //Nếu danh sách có phần tử thì, 
    tail->next = newNode;// con trỏ next của tail trỏ đến newNode
    newNode->prev = tail;// con trỏ prev của newNode trỏ đến tail
    tail = newNode;//dịch chuyển tail về newNode, vì tail luôn luôn quản lý phần tử cuối cùng trong danh sách
}

Bước 4: Duyệt DSLK đôi từ đầu về cuối và từ cuối về đầu.

/* hiển thị từ đầu đến cuối */
void Print() {
    struct Node* temp = head;
    printf("\nĐầu đến cuối: ");
    while(temp != NULL) {
        printf("%d ",temp->data);
        temp = temp->next;
    }
    printf("\n");
}
  
/* hiển thị từ cuối về đầu */
void ReversePrint() {
    struct Node* temp = tail;
    if(temp == NULL) return; // empty list, exit
    // Traversing backward using prev pointer
    printf("\nCuối về đầu: ");
    while(temp != NULL) {
        printf("%d ",temp->data);
        temp = temp->prev;
    }
    printf("\n");
}

Full code:

#include <iostream>
using namespace std;
/* tạo cấu trúc node */
struct Node  {
    int data;
    struct Node* next;
    struct Node* prev;
};
 
struct Node *head, *tail; // Khởi tạo Node head global của dslk đôi.
  
/* tạo node mới */
struct Node* CreateNode(int x) {
    struct Node* newNode
        = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = x;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}
/* hiển thị từ đầu đến cuối */
void Print() {
    struct Node* temp = head;
    printf("\nĐầu đến cuối: ");
    while(temp != NULL) {
        printf("%d ",temp->data);
        temp = temp->next;
    }
    printf("\n");
}
  
/* hiển thị từ cuối về đầu */
void ReversePrint() {
    struct Node* temp = tail;
    if(temp == NULL) return; // empty list, exit
    // Traversing backward using prev pointer
    printf("\nCuối về đầu: ");
    while(temp != NULL) {
        printf("%d ",temp->data);
        temp = temp->prev;
    }
    printf("\n");
}
/* thêm node vào đầu danh sách */
void InsertFirst(int x) {
  //sử dụng hàm tạo Node tạo một Node mới
    struct Node* newNode = CreateNode(x);
   //nếu danh sách rỗng thì node chèn vào vừa là node đầu vừa là node cuối
    if(head == NULL) {
        head = newNode;
        tail = newNode;
        return;
    }
    //Nếu danh sách không rỗng thì, dịch chuyển Node head về node mới chèn, và cho con trỏ của newNode trỏ đến Node head
    head->prev = newNode;
    newNode->next = head;
    head = newNode;
}
/* thêm node vào cuối danh sách */
void InsertLast(int x) {
  //sử dụng hàm tạo Node để tạo node mới newNode
    struct Node* newNode = CreateNode(x);
    //Nếu danh sách rỗng thì newNode vừa là node đầu vừa là node cuối
    if(head == NULL) {
        head = newNode;
        tail = newNode;
        return;
    }
    //Nếu danh sách có phần tử thì, 
    tail->next = newNode;// con trỏ next của tail trỏ đến newNode
    newNode->prev = tail;// con trỏ prev của newNode trỏ đến tail
    tail = newNode;//dịch chuyển tail về newNode, vì tail luôn luôn quản lý phần tử cuối cùng trong danh sách
}
int main() {
  
    head = NULL;
 //gọi hàm thêm node vào đầu danh sách
     
    InsertFirst(2);
    InsertFirst(3);
    InsertFirst(4);
    cout<<"Danh sách sau khi thêm node vào đầu: \n";
    Print();
    ReversePrint(); 
    cout<<"\n----------end--------------\n";
 //gọi hàm thêm node vào cuối danh sách
    InsertLast(5);
    InsertLast(6);
    InsertLast(7);
    cout<<"Danh sách sau khi thêm node vào cuối: \n";
    Print(); 
    ReversePrint();
     
    cout<<"\n---------------------------------------\n";
    cout<<"Chương trình này được đăng tại codehow.net";
}

Kết quả:

bai34 02 png

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

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

Xóa node (Delete node) trong DSLK đơn

Xóa node (Delete node) 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