Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 16 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
16
Dung lượng
2,15 MB
Nội dung
3/16/2019 Nội dung CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT Data Structures & Algorithms DANH SÁCH LIÊN KẾT – LIST Kiểu danh sách Danh sách liên kết đơn Stack Queue KIỂU DANH SÁCH Các hình thức tổ chức danh sách • Danh sách = { phần tử có kiểu} • CTDL cho phần tử ? • Danh sách kiểu liệu tuyến tính : • Thể liên kết phần tử ? Mỗi phần tử có nhiều phần tử đứng trước Mỗi phần tử có nhiều phần tử đứng sau • Hai hình thức : Liên kết ngầm : Mảng (array) • Là kiểu liệu quen thuộc thực tế : Danh sách học sinh x0 Danh mục sách thư viện … xi xi+1 Liên kết tường minh :Danh sách liên kết (list) Danh bạ điện thoại x0 Danh sách nhân viên công ty … Mảng – Danh sách liên kết ngầm • Mối liên hệ phần tử thể ngầm: xi : phần tử thứ i danh sách xi , xi+1 kế cận danh sách • Phải lưu trữ liên tiếp phần tử nhớ công thức xác định địa phần tử thứ i: address(i) = address(1) + (i-1)*sizeof(T) • Ưu điểm : Truy xuất trực tiếp, nhanh chóng • Nhược điểm: x0 … xi xi+1 Sử dụng nhớ hiệu Kích thước cố định Các thao tác thêm vào , loại bỏ không hiệu x2 x1 x3 Danh sách liên kết tường minh • CTDL cho phần tử: Thông tin thân Địa phần tử kế danh sách x0 x1 x2 Mỗi phần tử biến động Ưu điểm + Sử dụng hiệu nhớ + Linh động số lượng phần tử x3 3/16/2019 Các loại danh sách liên kết • Danh sách liên Vòng: Phần tử cuối danh sách liên với phần tử đầu • Danh sách liên kết đơn: Mỗi phần tử liên kết với phần tử đứng sau danh sách A Danh sách liên kết đơn vòng B C D A B C B C D C D Danh sách liên kết đơi vịng Danh sách liên kết kép: Mỗi phần tử liên kết với phần tử đứng trước sau danh sách A danh sách A D B Danh sách liên Vòng: Phần tử cuối danh sách liên với phần tử đầu danh sách Danh sách liên kết đơn - LIST 10 Danh sách liên kết đơn - LIST Hình ảnh: Hình ảnh: NULL 11 12 3/16/2019 Danh sách liên kết đơn - LIST Danh sách liên kết đơn - LIST NODE Info pHead pNext pTail 4f 3f 4f 5f 5f NULL Trong ví dụ thành phần liệu số nguyên 13 Danh sách liên kết đơn - LIST 14 Danh sách liên kết đơn - LIST Cấu trúc liệu nút List đơn struct node { KDL Info; // Lưu thơng tin liệu có KDL struct node *pNext; //Lưu địa Node đứng sau }; Cấu trúc liệu DSLK đơn struct list { NODE *pHead;//Lưu địa Node List NODE *pTail; //Lưu địa Node cuối List }; Ví dụ 1: Hãy khai báo CTDL cho DSLK đơn số nguyên 15 Danh sách liên kết đơn - LIST 16 Danh sách liên kết đơn - LIST Ví dụ 2: Hãy khai báo CTDL cho DSLK đơn số thực 17 Ví dụ 3: Hãy khai báo CTDL cho DSLK đơn phân số 18 3/16/2019 Danh sách liên kết đơn - LIST Các thao tác LIST Ví dụ 4: Hãy khai báo CTDL cho DSLK đơn tọa độ điểm mặt phẳng oxy Khởi tạo DSLK đơn - Tạo DSLK đơn rỗng Tạo node có trường x Thêm node có khóa x vào danh sách Duyệt danh sách Hủy phần tử danh sách Sắp xếp danh sách liên kết đơn 19 Khởi tạo DSLK đơn Kiểm tra DSLK đơn rỗng 21 Tạo NODE cho DSLK đơn 22 Tạo NODE cho DSLK đơn Ví dụ 1: Định nghĩa hàm tạo node cho DSLK đơn số nguyên để chứa thông tin biết trước 23 24 3/16/2019 Tạo NODE cho DSLK đơn Tạo NODE cho DSLK đơn Ví dụ 2: Định nghĩa hàm tạo node cho DSLK đơn Ví dụ 3: Định nghĩa hàm tạo node cho DSLK đơn số thực để chứa thông tin biết trước phân số chứa thông tin biết trước 25 26 Tạo NODE cho DSLK đơn Thêm phần tử vào List đơn Ví dụ 4: Định nghĩa hàm tạo node cho DSLK đơn điểm tọa độ oxy chứa thông tin biết trước Nguyên tắc thêm: Khi thêm phần tử vào List có làm cho pHead, pTail thay đổi? Các vị trí cần thêm phần tử vào List: Thêm vào đầu List đơn Thêm vào cuối List đơn Thêm vào sau phần tử q list 27 Thêm NODE vào đầu List đơn Thêm NODE vào đầu List đơn l pHead 2f 3f 9f P N 10 2f pHead=P P 29 3f 4f 4f 8… P->pNext=pHead 30 3/16/2019 Thêm NODE vào đầu List đơn Nhập List đơn từ bàn phím Nhập list đơn từ bàn phím nhập thông void AddHead(LIST &l, Node* p) { if (l.pHead==NULL) { l.pHead = p; l.pTail = l.pHead; } else { p->pNext = l.pHead; l.pHead = p; } } tin node danh sách Yêu cầu người dùng nhập vào số node list Nhập vào node n list Tạo node Nhập giá trị info vào node vừa tạo (GetNode()) Thêm node vào list cách thêm vào đầu (addHead()) 32 Nhập List đơn từ bàn phím Nhập List đơn từ bàn phím Nhập list đơn từ bàn phím nhập thông VD 1: Nhập List số nguyên tin node danh sách 33 Nhập List đơn từ bàn phím 34 Nhập List đơn từ bàn phím VD 1: Nhập List số nguyên VD 1: Nhập List số nguyên 35 36 3/16/2019 Nhập List đơn từ bàn phím Nhập List đơn từ bàn phím VD 1: Nhập List số nguyên VD 2: Nhập List phân số 37 38 Nhập List đơn từ bàn phím Nhập List đơn từ bàn phím VD 2: Nhập List phân số VD 2: Nhập List phân số 39 40 Nhập List đơn từ bàn phím Duyệt DSLK đơn VD 2: Nhập List phân số pHead 1f 34 P 2f 3f 4f NULL pTail Tới cuối DSLK dừng 41 42 3/16/2019 Duyệt DSLK đơn Duyệt DSLK đơn • Bước 1: p = pHead;// p lưu địa phần tử đầu List • Bước 2: Trong (danh sách chưa hết) thực + xử lý phần tử p + p=p->pNext;// qua phần tử kế 44 Các thao tác duyệt list đơn Các thao tác duyệt list đơn Ví dụ 1: In danh sách liên kết số nguyên In danh sách liên kết đơn – In giá trị Info DSLK đơn Tìm kiếm node có trường Info thỏa mãn điều kiện 45 Các thao tác duyệt list đơn 46 Các thao tác duyệt list đơn Ví dụ 1: In danh sách liên kết số nguyên Ví dụ 2: Định nghĩa hàm tính tổng số lẻ dslk đơn số nguyên 47 48 3/16/2019 Chương trình với List đơn Chương trình với List đơn Tạo cấu trúc node list tương ứng (struct node, struct list) Tạo list rỗng (Init()) Yêu cầu người dùng nhập vào số node list Nhập vào node n list (inPut()) Tạo node Nhập giá trị info vào node vừa tạo (GetNode()) Thêm node vào list cách thêm vào đầu (addHead()) In dslk đơn vừa tạo (xuat()) 49 50 Thêm node vào cuối List đơn Thêm node vào cuối List đơn Ta cần thêm nút p vào cuối list đơn Bắt đầu: Nếu List rỗng + pHead = p; + pTail = pHead; Ngược lại + pTail->pNext=p; + pTail=p 51 Thêm node vào cuối List đơn void AddTail(LIST &l, Node *p) { if (l.pHead==NULL) { l.pHead = p; l.pTail = l.pHead; } else { l.pTail->Next = p; l.pTail = p; } } Thêm node vào cuối List đơn 3f 4f 4f 5f 5f pTail N9f pTail=P pTail->pNext 9f 6N P 3/16/2019 Thêm node p vào sau node q Thêm node p vào sau node q Ta cần thêm nút p vào sau nút q list đơn void InsertAfterQ(List &l, Node *p, Node *q) { if(q!=NULL) { p->pNext=q->pNext; q->pNext=p; if(l.pTail==q) l.Tail=p; } else AddHead(l,p);// thêm p vào đầu list Bắt đầu: Nếu (q!=NULL) B1: p->pNext = q->pNext B2: + q->pNext = p } + q = pTail pTail=p Thêm node p vào sau node q Hủy phần tử List đơn Nguyên tắc: Phải cô lập phần tử cần hủy trước hủy 3f 4f q 4f 9f 5f Các vị trị cần hủy 5f 9f Hủy phần tử đứng đầu List Hủy phần tử có khố x N5f q->pNext=P NULL Huỷ phần tử đứng sau q danh sách liên kết đơn P->pNext=q->pNext P Hủy phần tử đầu List Bắt đầu: Nếu (pHead!=NULL) B1: p=pHead B2: + pHead = pHead->pNext // p->pNext + delete (p) B3: Nếu pHead==NULL pTail=NULL // Danh sách ban đầu có phần tử Ở phần trên, phần tử DSLK đơn cấp phát vùng nhớ động hàm new, giải phóng vùng nhớ hàm delete Hủy phần tử đầu List Hủy hàm trả 1, ngược lại hàm trả int RemoveHead(List &l, int &x) { Node *p; if(l.pHead!=NULL) { p=l.pHead; x=p->Info; //lưu Data nút cần hủy l.pHead=l.pHead->pNext; // l.pHead = p->pNext delete p; if(l.pHead==NULL) l.pTail=NULL; return 1; } return 0; } 10 3/16/2019 Hủy phần tử đầu List Hủy phần tử sau phân tử q List Bắt đầu Nếu (q!=NULL) //q tồn List pHead=pHead->pNext pHead 2f 1f 2f 3f 3f 4f pTail B1: p=q->pNext;// p phần tử cần hủy 4f … B2: Nếu (p!=NULL) // q phần tử cuối NULL + q->pNext=p->pNext;// tách p khỏi xâu + (p== pTail) // nút cần hủy nút cuối P=pHead pTail=q; P + delete p;// hủy p Hủy phần tử sau phân tử q List int RemoveAfterQ(List &l, Node *q, int &x) { Node *p; if(q!=NULL) { p=q->pNext; //p nút cần xoá if(p!=NULL) // q không phài nút cuối { if(p==l.pTail) //nút cần xoá nút cuối l.pTail=q;// cập nhật lạ pTail q->pNext=p->pNext; x=p->Info; delete p; } return 1; } else return 0; } Hủy phần tử sau phân tử q List q pHead 1f 2f p-=q->pNext p 2f 3f 4f 3f3f 4f 4f … q->pNext=p->pNext Hủy phần tử có khóa x Hủy phần tử có khóa x Bước 1: Tìm phần tử p có khoá x, q đứng trước p Bước 2: Nếu (p!=NULL) //tìm thấy phần tử có khố x Hủy p khỏi List cách hủy phần tử đứng sau q Ngược lại Báo khơng tìm thấy phần tử có khố int RemoveX(List &l, int x) { Node *p,*q = NULL; p=l.Head; while((p!=NULL)&&(p->Info!=x)) //tìm { q=p; p=p->Next; } if(p==NULL) //khơng tìm thấy phần tử có khố x return 0; if(q!=NULL)//tìm thấy phần tử có khố x DeleteAfterQ(l,q,x); else //phần tử cần xoá nằm đầu List RemoveHead(l,x); return 1; } 11 3/16/2019 Tìm phần tử DSLK đơn Tìm phần tử DSLK đơn Tìm (hàm trả về), bước thuật tốn tìm nút có Info x list đơn Bước 1: p=pHead;// địa phần tử đầu list đơn Hàm tìm phần tử có Info = x, hàm trả địa nút có Info = x, ngược lại hàm trả NULL Node *Search(LIST l, Data x) { Bước 2: Node Trong p!=NULL p->Info!=x *p; p = l.pHead; p=p->pNext;// xét phần tử kế while((p!= NULL)&&(p->Info != x)) Bước 3: p = p->pNext; + Nếu p!=NULL p lưu địa nút có return p; Info = x } + Ngược lại : Khơng có phần tử cần tìm Tìm phần tử DSLK đơn Hủy DSLK đơn Bước 1: pHead 1f 34 2f 3f 4f 5f Trong (danh sách chưa hết) thực 56 •B11: p = pHead; P pHead = pHead->pNext;// cập nhật pHead X= •B12: Tìm thấy, hàm trả địa nút tìm thấy 4f Hủy p Bước 2: pTail = NULL;// bảo tồn tính qn xâu rỗng Hủy DSLK đơn void RemoveList(List &l) Hủy DSLK đơn pHead { Node *p; while(l.pHead!=NULL)//còn phần tử List 1f 2f pTail 2f 3f 3f 4f 4f 5f 5f N { p = l.pHead; l.pHead = p->pNext; p delete p; } } 12 3/16/2019 Sắp xếpDSLK đơn Sắp xếp DSLK đơn Có hai cách tiếp cận Cách 1: Thay đổi thành phần Info pTail pHead 3f 4f 4f 5f pHead 5f pHead 3f Cách 2: Thay đổi thành phần pNext (thay đổi trình tự móc nối phần tử cho tạo lập nên thứ tự mong muốn) N pTail 4f 4f 4f 4f 5f 5f N pHead 5f 5f 3f pTail N Sắp xếp DSLK đơn Ưu – Nhược điểm Thay đổi thành phần Info (dữ liệu) Ưu: Cài đặt đơn giản, tương tự xếp mảng Nhược: • Địi hỏi thêm vùng nhớ hoán vị nội dung phần tử phù hợp với xâu có kích thước Info nhỏ • Khi kích thước Info (dữ liệu) lớn chi phí cho việc hốn vị thành phần Info lớn làm cho thao tác xếp chậm Thay đổi thành phần pNext Ưu: • Kích thước trường khơng thay đổi, khơng phụ thuộc vào kích thước chất liệu lưu nút thao tác xếp nhanh Nhược: Cài đặt phức tạp 4f 3f 5f pTail 5f N 4f Sắp xếp DSLK đơn Selection Sort void SelectionSort(LIST &l) while(q!=NULL) { { Node *p,*q,*min; if(q->InfoInfo) p=l.pHead; min=q; while(p!=l.pTail) q=q->pNext; { } min=p; HV(min->Info,p->Info); q=p->pNext; p=p->pNext; } } Sắp xếp DSLK đơn Các thuật toán xếp xâu (List) thay đổi thành phần pNext (thành phần liên kết) có hiệu cao như: Thuật tốn xếp Quick Sort Sắp xếp DSLK đơn – Quick Sort • Bước 1: Chọn X phần tử đầu xâu L làm phần tử cầm canh Loại X khỏi L • Bước 2: Tách xâu L làm xâu L1(gồm phần tử nhỏ x) L2 (gồm phần tử lớn X) Thuật tốn xếp Merge Sort • Bước 3: Nếu (L1 !=NULL) QuickSort(L1) Thuật tốn xếp Radix Sort • Bước 4: Nếu (L2!=NULL) QuickSort(L2) • Bước 5: Nối L1, X, L2 lại theo thứ tự ta có xâu L xếp 13 3/16/2019 Sắp xếp DSLK đơn – Quick Sort Cho danh sách liên kết gồm phần tử sau: pTail Sắp xếp DSLK đơn – Quick Sort Sắp xếp L1 Sắp xếp L2 pHead Chọn x=6 cầm canh, tách L2 thành L21 L22 X2 = X= pHead L1 (X) L21 (X) pTail pHead L2 (>X) pTail pHead pTail pTail pHead L22 (>X) Sắp xếp DSLK đơn – Quick Sort Nối L21, X2, L22 thành L2 Sắp xếp DSLK đơn – Quick Sort void QuickSort(List &l) { Node *p,*X;//X lưu địa phần tử cầm canh pTail pHead L2 List l1,l2; if(l.pHead==l.pTail) return;//đã có thứ tự CreateList(l1); CreateList(l2); X=l.pHead; Nối L1, X, L2 thành L l.pHead=X->pNext; while(l.pHead!=NULL)//tách L = L1 va L2 { pTail pHead p=l.pHead; l.pHead=p->pNext; p->pNext=NULL; if(p->InfoInfo) AddHead(l1,p); else AddHead(l2,p); } Sắp xếp DSLK đơn – Quick Sort QuickSort(l1);//Gọi đệ quy xếp L1 QuickSort(l2);//Gọi đệ quy xếp L2 if(l1.pHead!=NULL)//nối l1, l2 va X vao l { l.pHead=l1.pHead; l1.pTail->pNext=X;//nối X vào } else l.pHead=X; X->pNext=l2.pHead; if(l2.pHead!=NULL) //l2 có phần tử l.pTail=l2.pTail; else //l2 khơng có phần tử l.pTail=X; Sắp xếp DSLK đơn – Merge Sort • Bước 1: Phân phối luân phiên đường chạy xâu L vào xâu L1 L2 • Bước 2: Nếu L1 != NULL Merge Sort (L1) • Bước 3: Nếu L2 != NULL Merge Sort (L2) • Bước 4: Trộn L1 L2 xếp lại ta có xâu L xếp • Khơng tốn thêm khơng gian lưu trữ cho dãy phụ } 14 3/16/2019 Sắp xếp DSLK đơn – Merge Sort Cho danh sách liên kết gồm phần tử sau: pTail Sắp xếp DSLK đơn – Merge Sort Sắp xếp L1 Phân phối đường chạy L1 vào L11, L12 pHead pTail L12 pTail pHead L2 pHead pHead 4 L11 Phân phối đường chạy L1 vào L1, L2 pTail L1 pTail pHead Trộn L11 L12 vào L1 pTail pHead L1 Sắp xếp DSLK đơn – Merge Sort Sắp xếp DSLK đơn – Merge Sort Sắp xếp L2 Phân phối đường chạy L2 vào L21, L22 L21 pTail pHead pTail pHead L22 Trộn L1, L2 thành L pTail pHead 2 Trộn L21, L22 thành L2 pTail pHead L2 Bài tập Yêu cầu: Thông tin sinh viên gồm, mã số sinh viên, tên sinh viên, điểm trung bình Hãy khai báo cấu trúc liệu dạng danh sách liên kết để lưu danh sách sinh viên nói Nhập danh sách sinh viên, thêm sinh viên vào đầu danh sách (việc nhập kết thúc tên sinh viên rỗng) Tìm sinh viên có lớp học hay khơng Xố sinh viên có mã số x (x nhập từ bàn phím) Liệt kê thơng tin sinh viên có điểm trung bình lớn hay Bài tập Xếp loại in thông tin sinh viên, biết cách xếp loại sau: ĐTB =50 ĐTB=6.5 ĐTB < 7.0: Loại trung bình ĐTB>=7.0 ĐTB =8.0 ĐTB < 9.0: Loại giỏi ĐTB>=9.0 : Loại xuất sắc Sắp xếp in danh sách sinh viên tăng theo điểm trung bình Chèn sinh viên vào danh sách sinh viên tăng theo điểm trung bình nói trên, cho sau chèn danh sách sinh viên tăng theo điểm trung bình vv 15 3/16/2019 Slide tham khảo từ • Slide tham khảo từ: • Slide CTDL GT, Khoa Khoa Học Máy Tính, ĐHCNTT • Slide CTDL GT, Thầy Nguyễn Tấn Trần Minh Khang, ĐH CNTT • Congdongcviet.com • Cplusplus.com 91 92 16 ... Tạo NODE cho DSLK đơn 22 Tạo NODE cho DSLK đơn Ví dụ 1: Định nghĩa hàm tạo node cho DSLK đơn số nguyên để chứa thông tin biết trước 23 24 3/ 16/ 2019 Tạo NODE cho DSLK đơn Tạo NODE cho DSLK đơn Ví... 40 Nhập List đơn từ bàn phím Duyệt DSLK đơn VD 2: Nhập List phân số pHead 1f 34 P 2f 3f 4f NULL pTail Tới cuối DSLK dừng 41 42 3/ 16/ 2019 Duyệt DSLK đơn Duyệt DSLK đơn • Bước 1: p = pHead;// p... khai báo CTDL cho DSLK đơn số thực 17 Ví dụ 3: Hãy khai báo CTDL cho DSLK đơn phân số 18 3/ 16/ 2019 Danh sách liên kết đơn - LIST Các thao tác LIST Ví dụ 4: Hãy khai báo CTDL cho DSLK đơn tọa độ