Trong hai bài trước, ta đã tìm hiểu được khái quát và việc thêm một phần tử vào trong danh sách liên kết đôi. Việc thêm phần tử vào danh sách liên kết đôi ở bài trước chỉ dừng lại ở việc gọi hàm voi ThemDau() hoặc voi ThemCuoi(). Tuy nhiên, vấn đề ở đây ta mong muốn lấy được dữ liệu của node vừa được thêm vào danh sách liên kết đôi vì vậy ta cần đi xây dựng các hàm để nhập xuất danh sách liên kết đôi.

1.Nhập N phần tử vào danh sách liên kết đôi

Để xây dựng được hàm nhập N phần tử vào trong danh sách liên kết đôi, ta cần hiểu được những hàm sau đây:

  • Hàm tạo một node trong danh sách liên kết
  • Các hàm void ThemDau() hoặc void ThemCuoi() ở bài trước.

Nếu như bạn đã từng học về danh sách liên kết đơn thì việc nhập N phần tử vào danh sách liên kết đơn cũng giống như nhập N phần tử vào danh sách liên kết đôi, tuy nhiên ở đây tôi sẽ xây dựng lại nhanh hàm nhập cho danh sách liên kết đôi để phục vụ những bài sau này:

void Nhap(DLIST &ds, int n){
    //duyet N lan
    for(int i = 0; i < n; i++){
        //nhap du lieu la so nguyen int x
        int x;
        printf("Nhap vao so x: ");
        scanf("%d",&x);
        //tao node p
        NODE *p = new NODE;
        //dua du lieu vua nhap vao node p
        p = TaoNode(x);
        //dua node p vao ham them dau hoac them cuoi va truyen vao node p vua tao
        ThemDau(ds,p);
        //ThemCuoi(ds,p)
    }
}

2.Xuất dữ liệu của các node có trong danh sách liên kết đôi

Như đã đề cập ở phần đầu của bài viết, khi sử dụng các hàm void ThemDau() hoặc void ThemCuoi() ở bài trước ta vẫn chưa hiển thị được các giá trị của node đó ra màn hình để phục vụ việc kiểm tra, tìm kiếm, sắp xếp….

Để thực xây đựng được hàm xuất dữ liệu của các node có trong danh sách ta có thể dùng vòng lặp for hoặc vòng lặp while để duyệt qua các node có trong danh sách liên kết đôi đó. Hàm xuất này cũng giống hàm xuất của danh sách liên kết đơn.

Hàm xuất sử dụng vòng lặp for

void Xuat(DLIST ds){
    //khoi tao mot node
    NODE *p = new NODE;
    //duyet tu dau danh sach den cuoi danh sach voi dieu kien p!=NULL
    for(p = ds.pHead; p!= NULL; p=p->next){
        //hien thi du lieu cua tung node
        printf("%d\n",p->data);
    }
}

Hàm xuất sử dụng vòng lặp while

void Xuat(DLIST ds){
    //tao node p
    NODE *p;
    p = ds.pHead;
    //trong khi node p chua bang NULL (p chua la phan tu cuoi)
    while (p!=NULL){
        //hien thi du lieu
        printf("%d\n",p->data);
        //chuyen sang node tiep theo
        p=p->next;
    }
}

3.Chương trình nhập xuất trong danh sách liên kết đôi hoàn chỉnh

Chương trình dưới đây tôi sẽ nhập 5 phần tử là: 11,22,33,44,55 vào danh sách liên kết đôi theo thứ tự chèn mỗi phần tử sau vào cuối danh sách.

#include <stdio.h>
#include <stdlib.h>
struct Node
{
    //khai bao thanh phan du lieu co kieu int
    int data;
    //khai bao con tro next co kieu Node de chua dia chi phan tu sau
    Node *next;
    //khai bao con tro prev co kieu Node de chua dia chi phan tu truoc
    Node *prev;
};
typedef struct Node NODE;

struct doulist{
    //thanh phan dau danh sach
    NODE *pHead;
    //thanh phan cuoi danh sach
    NODE *pTail;
};
typedef struct doulist DLIST;

void KhoiTao(DLIST &ds){
    //dat dia chi dau danh sach bang NULL
    ds.pHead = NULL;
    //dat dia chi cuoi danh sach bang NULL
    ds.pTail = NULL;
}

NODE* TaoNode(int x) {
    //tao mot node p moi
    NODE *p;
    p = new NODE;
    //neu p==NULL thi khong du bo nho va ket thuc viec tao node
    if (p==NULL) {
        printf ("KHONG DU BO NHO");
        return NULL;
    }
    //gan thanh phan data = x
    p->data=x;
    //gan con tro next = NULL
    p->next=NULL;
    //gan con tro prev = NULL
    p->prev = NULL;
    //tra ve node p da tao
    return p;
}

void ThemDau(DLIST &ds, NODE *p) {
    //neu danh sach rong thi them vao node dau va cuoi
    if (ds.pHead == NULL){
        ds.pHead = ds.pTail = p;
    }else {
        //dat con tro next cua node can them toi node dau danh sach
        p->next = ds.pHead;
        //dat con tro prev cua node dau ve node p 
        ds.pHead->prev = p;
        //gan lai node dau cua danh sach bang node p
        ds.pHead = p;
    }
}
void ThemCuoi(DLIST &ds, NODE*p){
    //kiem tra danh sach rong neu rong thi them vao dau va cuoi
    if (ds.pHead == NULL){
        ds.pHead = ds.pTail = p;
    }else{
        //dat con tro next cua pTail hien tai vao p la node can them cuoi
        ds.pTail->next = p;
        //dat con tro prev cua node p ve phan tu cuoi danh sach
        p->prev = ds.pTail;
        //thay doi lai phan tu cuoi danh sach
        ds.pTail = p;
    }
}
void Nhap(DLIST &ds, int n){
    //duyet N lan
    for(int i = 0; i < n; i++){
        //nhap du lieu la so nguyen int x
        int x;
        printf("Nhap vao so %d: ",i);
        scanf("%d",&x);
        //tao node p
        NODE *p = new NODE;
        //dua du lieu vua nhap vao node p
        p = TaoNode(x);
        //dua node p vao ham them cuoi va truyen vao node p vua tao
        ThemCuoi(ds,p);
    }
}
void Xuat(DLIST ds){
    //khoi tao mot node
    NODE *p = new NODE;
    //duyet tu dau danh sach den cuoi danh sach voi dieu kien p!=NULL
    for(p = ds.pHead; p!= NULL; p=p->next){
        //hien thi du lieu cua tung node
        printf("%d\n",p->data);
    }
}
int main(){
    //khai bao mot danh sach lien ket doi
    DLIST ds;
    //nhap n phan tu 
    int n;
    printf("NHAP N: ");
    scanf("%d",&n);
    //khoi tao danh sach
    KhoiTao(ds);
    //goi ham nhap tryuyen vao danh sach va N phan tu
    Nhap(ds,n);
    //goi ham xuat cac du lieu co trong danh sach
    printf("DANH SACH VUA NHAP\n");
    Xuat(ds);
}
NHAP N: 5

Nhap vao so 0: 11

Nhap vao so 1: 22

Nhap vao so 2: 33

Nhap vao so 3: 44

Nhap vao so 4: 55

DANH SACH VUA NHAP

11

22

33

44

55

Chương trình trên trong khi sử dụng hàm nhập là void Nhap() ta gọi hàm void ThemCuoi() nên các phần tử được nhập vào danh sách sau khi gọi hàm xuất sẽ hiển thị ra màn hình: 11,22,33,44,55

Tuy nhiên, nếu ta gọi gàm void ThemDau() để nhập vào danh sách thì sẽ nhận được kết quả sau khi gọi hàm xuất đó là: 55,44,33,22,11