Sau khi có danh sách liên kết đôi và đã được nhập xuất các phần tử vào danh sách liên kết đôi đó, đôi khi ta cần thực hiện việc tìm kiếm và kiểm tra các phần tử trong danh sách đó nhằm phục vụ cho mục đích sắp xếp, sửa hoặc xóa các phần tử trong danh sách liên kết đôi.
1.Cách tìm kiếm một phần tử trong danh sách liên kết đôi
Hàm tìm kiếm của chúng ta đang cần xây dựng với mong muốn đầu vào là danh sách cần tìm kiếm và khóa (hay dữ liệu) cần tìm kiếm trong danh sách.
Việc tìm kiếm thành công sẽ trả cho chúng ta đầu ra là con trỏ tới khóa cần tìm kiếm (hay chính là phần tử được tìm thấy).
Để thực hiện việc tìm kiếm trong danh sách liên kết đôi ta cần thực hiện các bước sau:
- B1: Tạo Node p và gán bằng đầu danh sách: p=pHead
- B2: Sử dụng vòng lặp while (p!= NULL) và (p->data != x)
- Thực hiện p = p->next; // p trỏ tới phần tử kế tiếp
- B3: Kiểm tra kết quả sau khi thực hiện vòng lặp ở B2
- Nếu p==NULL không có phần tử cần tìm;
- Ngược lại: nếu p != NULL thì trỏ đến phần tử cần tìm
2.Hàm tìm kiếm một phần tử trong danh sách liên kết đôi
Ở phần trên, tôi đã trình bày các bước để thao tác tìm kiếm phần tử có trong danh sách theo dữ liệu x làm khóa tìm kiếm.
Các bước trên có vẻ hơi “mông lung” nên bạn đọc có thể đọc code ở dưới đây để hiểu rõ hơn về hàm tìm kiếm:
NODE* TimKiem(DLIST ds, int x){ //tao node p NODE *p; //gan p bang phan tu dau danh sach p = ds.pHead; //su dung vong lap while ((p!=NULL) && (p->data!=x)){ p=p->next; } //tra ve ket qua, neu NULL thi khong tim thay return p; }
Hàm tìm kiếm trên có kiểu trả về là NODE và truyền vào danh sách cần tìm kiếm và khóa int x để tìm kiếm trong danh sách đó.
Chú ý rằng hàm trên dù có tìm thấy kết quả hay không thì đều trả về một node p. Nếu p = NULL thì ta kết luận không tìm thấy, và nếu tìm thấy kết quả thì p != NULL và ta nhận được kết quả chính là node p.
3.Chương trình tìm kiếm một phần tử trong danh sách liên kết đôi
Trước khi sử dụng hàm tìm kiếm, tôi cần đảm bảo rằng đã có các phần tử nằm trong danh sách cần tìm kiếm, vì thế tôi sẽ nhập các phần tử vào trong danh sách trước sau đó mới gọi hàm tìm kiếm.
#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 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); } } NODE* TimKiem(DLIST ds, int x){ //tao node p NODE *p; //gan p bang phan tu dau danh sach p = ds.pHead; //su dung vong lap while ((p!=NULL) && (p->data!=x)){ p=p->next; } //tra ve ket qua, neu NULL thi khong tim thay return p; } 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 gia tri can tim kiem int x; printf("NHAP GIA TRI CAN TIM KIEM: "); scanf("%d",&x); //goi ham tim kiem truyen vao gia tri x va gan vao node p NODE *p = TimKiem(ds,x); //kiem tra ket qua tim kiem if(p == NULL){ printf("\nKHONG TIM THAY KET QUA"); }else{ printf("\nTIM THAY KET QUA: "); printf("%d",p->data); } }
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 NHAP GIA TRI CAN TIM KIEM: 44 TIM THAY KET QUA: 44 |
Sau khi gọi NODE TimKiem() và gán vào NODE p ta sẽ kiểm tra điều kiện nếu p == NULL thì không tìm thấy kết quả. Ngược lại thì p!= NULL nghĩa là tìm thấy kết quả trong danh sách với khóa X cần tìm.