1 / 52

Xin vui lòng yên lặng!

Xin vui lòng yên lặng!. Danh sách liên kết (Linked List). Giới thiệu. Định nghĩa: Là danh sách bao gồm các phần tử kết nối với nhau bằng 1 hay nhiều mối liên kết. Các thao tác trên danh sách. Khởi tạo danh sách rỗng Kiểm tra danh sách rỗng?

virote
Télécharger la présentation

Xin vui lòng yên lặng!

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Xin vui lòng yên lặng! Lê Mậu Long

  2. Danh sách liên kết(Linked List) Lê Mậu Long

  3. Giới thiệu • Định nghĩa: Là danh sách bao gồm các phần tử kết nối với nhau bằng 1 hay nhiều mối liên kết Lê Mậu Long

  4. Các thao tác trên danh sách • Khởi tạo danh sách rỗng • Kiểm tra danh sách rỗng? • Chèn phần tử vào danh sách • Xóa phần tử trong danh sách • Tìm kiếm phần tử trong danh sách • Khởi đầu từ đầu danh sách • Lấy dữ liệu 1 phần tư • Chuyển sang phần tử kế tiếp • Hết danh sách • …. Lê Mậu Long

  5. Danh sách liên kết đơn • Là danh sách mà mỗi phần tử có 1 mối liên kết để kết nối với phần tử kế tiếp • Cài đặt: dựa trên con trỏ, bao gồm: • 3 con trỏ: head (đầu ds), pos (phần tử hiện hành), và rear (cuối ds) • biến count: số phần tử của danh sách head pos rear Lê Mậu Long

  6. Mô tả kiểu dữ liệu typedef struct nodet { elem data; struct nodet *next; } node; typedef node *nodeptr; data next Lê Mậu Long

  7. head pos rear typedef struct { nodeptr head, pos, rear; int count; } list; Lê Mậu Long

  8. Khởi tạo danh sách rỗng Gán • head, pos và rear = NULL • count = 0 // Hàm khởi tạo void createlist(list &l) { l.head = l.pos = l.rear = NULL; l.count = 0; } Lê Mậu Long

  9. Kiểm tra danh sách rỗng? • Kiểm tra số phần tử = 0 int emptylist(list l) { return l.count == 0; } Lê Mậu Long

  10. head pos rear Chèn phần tử x vào danh sách – cục bộ (local) • Cấp phát bộ nhớ cho newp và gán dữ liệu • Chèn ở đầu ds (p==NULL) newp->next = head; head = newp; newp Lê Mậu Long

  11. Chèn sau phần tử p (p!=NULL) newp->next = p->next; p->next = newp; head pos p rear newp Lê Mậu Long

  12. Trường hợp chèn cuối (newpnext == NULL) • Thay đổi rear rear = newp; head pos p rear newp Lê Mậu Long

  13. void insertlist(list &l, elem &x, nodeptr p) { nodeptr newp = new node; memcpy(&newp->data, &x, sizeof(elem)); if (p==NULL) { newp->next = l.head; l.head = newp; } else { newp->next = p->next; p->next = newp; } if (newp->next == NULL) l.rear = newp; l.count++; } Lê Mậu Long

  14. Các hàm chèn phần tử – toàn cục (global) • Chèn đầu danh sách void inserthead(list &l, elem &x) { insertlist(l, x, NULL); } • Chèn vị trí hiện hành void insertpos(list &l, elem &x) { insertlist(l, x, l.pos); } • Chèn cuối danh sách void insertrear(list &l, elem &x) { insertlist(l, x, l.rear); } Lê Mậu Long

  15. t head p t rear rear head Xoá phần tử trong danh sách – cục bộ • Xoá phần tử đầu danh sách (p=NULL) t = head; head = t->next; • Xoá phần tử sau p (p!=NULL) t = p->next; p->next = t->next; p Lê Mậu Long

  16. void deletelist(list &l, nodeptr p) { nodeptr t; if (p==NULL) { t = l.head; l.head = t->next; } else { t = p->next; p->next = t->next; } if (t->next == NULL) l.rear = p; delete t; l.count--; } Lê Mậu Long

  17. Các hàm xóa phần tử – toàn cục • Xóa phần tử đầu danh sách void deletehead(list &l) { deletelist(l, NULL); } • Xóa phần tử tại vị trí hiện hành void deletepos(list &l) { deletelist(l, l.pos); } Lê Mậu Long

  18. head pos c rear 1 8 2 5 4 3 Tìm kiếm trên DS X=5 • Khởi đầu từ đầu danh sách (pos = NULL; c = head) • Khi chưa hết ds và chưa tìm thấy Chuyển sang phần tử kế tiếp (pos = c; c = cnext) Lê Mậu Long

  19. Tìm kiếm trên DS – bản nháp int searchlist(list &l, elem x) { nodeptr c = l.head; l.pos = NULL; while (c!=NULL && x!=c->data) { l.pos = c; c = c->next; } return c!=NULL; } Lê Mậu Long

  20. Tìm kiếm trên DS – viết lại int searchlist(list &l, elem x, int (*comp)(elem, elem)) { nodeptr c = l.head; l.pos = NULL; while (c!=NULL && comp(x, c->data)!=0) { l.pos = c; c = c->next; } return c!=NULL; } Lê Mậu Long

  21. Tìm kiếm trên DS có thứ tự int searchorderlist(list &l, elem x, int (*comp)(elem, elem)) { nodeptr c = l.head; l.pos = NULL; while (c!=NULL && comp(x, c->data)>0) { l.pos = c; c = c->next; } if (c!=NULL && comp(x, c->data)<0) return 0; return c!=NULL; } Lê Mậu Long

  22. int searchorderlist(list &l, elem x, int (*comp)(elem, elem)) { nodeptr c = l.head; l.pos = NULL; while (c!=NULL && comp(x, c->data)>0) { l.pos = c; c = c->next; } if (c!=NULL && comp(x, c->data)<0) return 0; return c!=NULL; } // Hàm so sánh trên khoá int ss(int x, int y) { return x-y; } //Đoạn chương trinh nhập dãy createlist(l); cout<<"\nNhap day:"; do { cin>>x; if (x>0) { searchorderlist(l, x, ss); insertpos(l, x); } } while (x>0); Ví dụ Lê Mậu Long

  23. Khởi đầu từ đầu danh sách void start(list &l) { l.pos = l.head; } • Chuyển sang phần tử kế tiếp void skip(list &l) { if (l.pos == NULL) l.pos = l.head; else l.pos = l.pos->next; } Lê Mậu Long

  24. Kiểm tra hết danh sách int eol(list l) { return l.pos == NULL; } • Lấy dữ liệu 1 phần tử void getdata(list l, elem &x) { memcpy(&x, &l.pos->data, sizeof(elem)); } • Số phần tử trong danh sách int nolist(list l) { return l.count; } Lê Mậu Long

  25. 1 0 0 1 1 Ngăn xếp (Stack) • Là cấu trúc bao gồm các phần tử được truy xuất theo nguyên tắc “vào sau, ra trước” (Last In, First Out – LIFO) Ví dụ: Chồng đĩa, đổi số ra nhị phân 19 1 9 1 4 0 2 0 1 1 Lê Mậu Long

  26. Các thao tác trên Stack 4 thao tác cơ bản trên stack • Khởi tạo stack rỗng: CreateStack(s) • Kiểm tra stack rỗng: EmptyStack(s) • Đưa phần tủ vào Stack: Push(s, x) • Lấy phần tủ ra khỏi Stack:Pop (s, x) Lê Mậu Long

  27. Sử dụng Mảng e[Max] phần tử kiểu elem (elementtype) Chỉ số top để chỉ đỉnh stack (nơi đưa vào, lấy ra) Tạo tập tin Stack.cpp: typedef struct { elem e[Max]; int top; } stack; 0 1 1 Cài đặt trên cơ sở mảng Max-1 top e Lê Mậu Long

  28. Các thao tác trên Stack • Khởi tạo stack s rỗng void createstack(stack &s) { s.top = -1; } • Kiểm tra stack s rỗng? int emptystack(stack s) { return s.top==-1; } Lê Mậu Long

  29. Đưa phần tử x vào stack s void push(stack &s, elem &x) { if (s.top==Max-1) exit(0); memcpy(&s.e[++s.top], &x, sizeof(elem)); } • Lấy phần tử x ra khỏi stack s void pop(stack &s, elem &x) { if (s.top==-1) exit(0); memcpy(&x, &s.e[s.top--], sizeof(elem)); } Lê Mậu Long

  30. #define Max 32 #include <iostream.h> typedef int elem; #include "stack.cpp" void main() { int i, n; stack s; cout<<"\nNhap so can doi:"; cin>>n; createstack(s); while (n>0) { i = n%2; push(s, i); n = n/2; } cout<<"Ket qua dang nhi phan :"; while (!emptystack(s)) { pop(s, i); cout<<i; } } Ví dụ: Đổi số ra nhị phân Lê Mậu Long

  31. Đệ qui và tổ chức đệ qui Lê Mậu Long

  32. Định nghĩa • Một định nghĩa được gọi là đệ qui nếu nó được định nghĩa trên chính nó một cách trực tiếp hay gián tiếp • Đệ qui luôn gồm 2 phần • Phần dừng • Phần đệ qui Lê Mậu Long

  33. Ví dụ Lê Mậu Long

  34. Giai thừa long gt(int n) { if (n==0) return 1; return n*gt(n-1); } void main() { cout<<gt(5); } Lê Mậu Long

  35. Khử bỏ đệ qui • Sử dụng Stack • Đệ qui được thay bằng: • Hàm đệ qui: Vòng lặp • Lời gọi đệ qui: Push các giá trị cục bộ • Thực hiện đệ qui: Pop các giá trị cục bộ • Lưu ý: Stack là cấu trúc LIFO Lê Mậu Long

  36. Bài toán Tháp Hanoi #include <iostream.h> void chuyen(int n, char A, char B, char C) { if (n==1) cout<<"\nChuyen "<<A<<" qua "<<C; else { chuyen(n-1, A, C, B); chuyen(1, A, ' ', C); chuyen(n-1, B, A, C); } } void main() { cout<<"\n============ De qui ==============="; chuyen(3, 'a', 'b', 'c'); } Lê Mậu Long

  37. Bài toán Tháp Hanoi không đệ qui • Khởi tạo stack s rỗng • Push 1 bộ (3, ‘A’, ‘B’, ‘C’) vào s • Lặp • Pop ra khỏi s 1 bộ (n, A, B, C); • Nếu n=1 thì • cout<<"\nChuyen "<<A<<" qua "<<C; • Ngược lại • Push 1 bộ (n-1, B, A, C) vào s • Push 1 bộ (1, A, ‘ ‘, C) vào s • Push 1 bộ (n-1, A, C, B) vào s • Cho đến khi s rỗng Lê Mậu Long

  38. Cài đặt trên cơ sở con trỏ • Cài đặt tương tự như danh sách liên kết đơn với 2 thao tác • Chèn đầu danh sách • Lấy ra ở đầu danh sách push s pop Lê Mậu Long

  39. Tạo tập tin Stack.cpp: typedef struct nodet { elem data; struct nodet *next; } node; typedef node *stack; void createstack(stack &s) { s = NULL; } Lê Mậu Long

  40. newp int emptystack(stack s) { return s==NULL; } void push(stack &s, elem &x) { stack newp = new node; memcpy(&newp->data, &x, sizeof(elem)); newp->next = s; s = newp; } s Lê Mậu Long

  41. t s void pop(stack &s, elem &x) { stack t = s; if (s==NULL) exit(0); memcpy(&x, &s->data, sizeof(elem)); s = s->next; delete t; } Chạy lại chương trình đổi nhị phân, nhận xét? Lê Mậu Long

  42. Hàng đợi (Queue) • Là cấu trúc bao gồm các phần tử được truy xuất theo nguyên tắc “vào trước, ra trước” (First In, First Out – FIFO) Ví dụ: Các vùng đệm giao tiếp giữa máy tính và các thiết bị Lê Mậu Long

  43. Các thao tác trên Queue 4 thao tác cơ bản trên queue • Khởi tạo queue rỗng: CreateQueue(q) • Kiểm tra queue rỗng: EmptyQueue(q) • Đưa phần tủ vào queue : AddQueue(q, x) • Lấy phần tủ ra khỏi queue : RemoveQueue(q, x) Lê Mậu Long

  44. Cài đặt trên cơ sở mảng • Sử dụng • Mảng e[Max] phần tử kiểu elem (elementtype) • Chỉ số • front để chỉ đầu hàng đợi (nơi lấy ra) • rear để chỉ cuối hàng đợi (nơi đưa vào) Hai chỉ số front và rear tăng xoay vòng • Tạo tập tin Queue.cpp: typedef struct { elem e[Max]; int front, rear; } queue; Lê Mậu Long

  45. Các thao tác trên Queue • Khởi tạo queue q rỗng void createqueue(queue &q) { q.front = q.rear = 0; } • Kiểm tra queue q rỗng? int emptyqueue(queue q) { return q.front == q.rear; } Lê Mậu Long

  46. Đưa phần tử x vào queue q void addqueue(queue &q, elem &x) { int nr = (q.rear + 1) % Max; if (nr == q.front) exit(0); memcpy(&q.e[q.rear], &x, sizeof(elem)); q.rear = nr; } • Lấy phần tử x ra khỏi queue q void removequeue(queue &q, elem &x) { if (q.front == q.rear) exit(0); memcpy(&x, &q.e[q.front], sizeof(elem)); q.front = (q.front + 1) % Max; } Lê Mậu Long

  47. Ví dụ: Radix sort • Sắp xếp dãy số nguyên dương tăng dần 71, 32, 53, 70, 50 , 63, 84, 15, 26, 19, 8, 37, 17, 46, 98, 21 8, 15, 17, 19, 21, 26, 32, 37, 46, 50, 53, 63, 70, 71, 84, 98 0 3 4 5 6 7 8 1 2 9 21 63 46 17 98 50 70 84 15 8 71 32 53 26 37 19 19 53 71 17 26 37 46 84 98 8 15 21 32 50 63 70 Lê Mậu Long

  48. Cài đặt trên cơ sở con trỏ • Cài đặt tương tự như danh sách liên kết đơn với 2 thao tác • Chèn cuối danh sách • Lấy ra ở đầu danh sách rear front remove add Lê Mậu Long

  49. Tạo tập tin Queue.cpp: typedef struct nodet { elem data; struct nodet *next; } node; typedef node *nodeptr; typedef struct { nodeptr front, rear; } queue; void createqueue(queue &q) { q.front = NULL; } Lê Mậu Long

  50. newp int emptyqueue(queue q) { return q.front == NULL; } void addqueue(queue &q, elem &x) { nodeptr newp = new node; memcpy(&newp->data, &x, sizeof(elem)); newp->next = NULL; if (q.front == NULL) q.front = newp; else q.rear->next = newp; q.rear = newp; } rear front Lê Mậu Long

More Related