Chương 4 cung cấp kiến thức về danh sách liên kết. Chương này gồm có những nội dung chính sau: Định nghĩa danh sách liên kết, danh sách liên kết đơn, danh sách liên kết kép. Mời các bạn cùng tham khảo để nắm bắt các nội dung chi tiết.
I Định nghĩa CHƯƠNG IV: • Danh sách liên kết đơn: phần tử danh sách liên kết với phần tử đứng sau Danh sách liên kết tập hợp phần tử liên kết móc nối liên tiếp với nhau, có kiểu truy cập Mỗi phần tử nút (Node) ! Số phần tử biến động ! Nút gồm hai phần: ! DANH SÁCH LIÊN KẾT – – ! Danh sách liên kết • Danh sách liên kết kép: phần tử danh sách liên kết với phần tử đứng trước đứng sau danh sách Data - Dữ liệu: thành phần liệu mà nút lưu trữ Linked - Liên kết: trỏ kiểu nút định nghĩa dùng để liên kết với nút khác • Danh sách liên kết vòng: danh sách mà phần tử cuối liên kết với phần tử đầu danh sách Có hai loại danh sách liên kết vịng: vịng đơn vịng kép Ví dụ: Data 14 *Phân loại danh sách liên kết Data Data 22 Danh sách liên kết 23 Danh sách liên kết II Danh sách liên kết đơn 1. Khai báo CTDL ! Khai báo CTDL DSLK Đơn: – Định nghĩa cấu trúc nút – Định nghĩa cấu trúc danh sách ! Cấu trúc nút gồm: – Info: kiểu cấu trúc – Next: kiểu trỏ ! Cấu trúc danh sách LK đơn gồm: ! Cú Info pháp định nghĩa nút: struct { Data info; //Khai báo liệu - struct struct Node *next; //khai báo liên kết }; Next (Dữ liệu) (liên kết) ! Trong đó: LIST Q; kiểu liệu khai báo để mô tả thành phần liệu chứa nút, kiểu định nghĩa sẵn – Tail Danh sách liên kết 25 Danh sách liên kết //tạo danh sách có tên Q 26 Ví dụ Danh sách liên kết Các thao danh sách đơn MSV struct SV hoten { dtb int MSV; char hoten[25]; float dtb; }; ! Cho thông tin Sinh viên gồm: mã sinh viên, Họ tên, Điểm trung bình ! Khai báo CTDL dạng danh sách liên kết đơn để lưu danh sách SV struct Node { SV info; struct Node *next; }; 27 pháp định nghĩa danh sách: struct LIST { Node Head; //Phần tử dầu danh sách Node Tail; //Phần tử cuối danh sách }; – Data: – Head 24 ! Cú Danh sách liên kết 28 MSV next hoten dtb ! Các next – Tạo danh sách danh sách – Chèn phần tử – Hủy phần tử – Tìm kiếm phần tử – Sắp xếp danh sách – … – Duyệt struct LIST { Node Head; Node Tail; }; Danh sách liên kết thao tác sau: 29 Danh sách liên kết a Tạo danh sách: ! Để b Chèn phần tử vào danh sách: *ĐN thủ tục get_node để tạo nút với thành phần liệu x có: Node* get_node( Data x ) { Node *p; p = new Node; tạo danh sách, gồm bước: – Khởi tạo danh sách rỗng – Tạo nút chứa thông tin ! Các vào đầu danh sách – Chèn vào cuối danh sách – Chèn vào sau phần tử q biết if ( p == NULL ) { printf(“Ko du bo nho”); exit(1); } p -> info = x; p -> next = NULL; return p; void init( List &Q ) { Q.Head = NULL; Q.Tail = NULL; } trường hợp sau – Chèn } => Tạo phần tử mới: new_element = get_node(x); 30 Danh sách liên kết 31 Danh sách liên kết 32 Chèn thêm phần tử vào đầu danh sách: Chèn thêm phần tử vào cuối danh sách: Q.Head Q.Tail Q.Head new_element Thuật toán Nếu danh sách rỗng Phần tử đầu phần tử chèn vào Phần tử cuối phần tử đầu Ngược lại (danh sách khác rỗng) Phần tử trỏ tới phần tử đầu Phần tử đầu phần tử chèn vào 33 Danh sách liên kết Danh sách liên kết Q.Head 2f 3f 3f 4f new_element Thuật toán Nếu danh sách rỗng: Phần tử đầu phần tử chèn vào Phần tử cuối phần tử đầu Ngược lại (danh sách khác rỗng): Phần tử cuối trỏ tới phần tử chèn vào Phần tử cuối phần tử chèn vào 4f 8… 9f Q.Head = P 34 10 P 2f P->Next = Q.Head Danh sách liên kết Q.Tail 35 Danh sách liên kết Chèn thêm phần tử sau phần tử q biết 3f 4f 4f 5f 5f N 9f Q.Tail->Next Q.Tai l Thuật tốn Nếu khơng có phần tử q " khơng chèn Nếu có tồn phần tử q -Phần tử móc tới phần tử sau phần tử q -Phần tử q móc tới phần tử -Nếu phần tử q phần tử cuối phần tử chèn phần tử cuối Q.Tail=P 9f 6N 36 8/4/16 PCTDL – Khoa CNTH Danh – Việnsách ĐH Mở liên HN kết 37 Danh sách liên kết 3f 4f 4f q 9f 5f q->Next = P 5f 9f N 5f P->Next = q->Next P 38 Danh sách liên kết *Thuật tốn B Tìm kiếm phần tử k danh sách # Ý tưởng: Danh sách đơn cho truy xuất tới phần tử " Áp dụng thuật toán tìm tuyến tính để xác định có phần tử k danh sách hay ko? # Để duyệt dùng trỏ p để duyệt qua nút danh sách 4f 5f 1f 2f 3f Q.Head 34 P X = 39 ! Bước sách 2: kiểm tra danh sách cịn phần tử chưa tìm thấy phần tử chuyển sang phần tử Lặp (p!=NULL) (p->info !=k) p = p -> next; ! Bước 3: – Nếu p != NULL: ! Tìm thấy ! p trỏ đến phần tử cần tìm – Ngược lại: ko tìm thấy (trả lại NULL) Tìm thấy, hàm trả địa nút tìm thấy 4f Danh sách liên kết Node *Search( LIST Q, Data k ) { Node *p; p = Q.Head; //p trỏ từ đầu danh ! Bước 56 1: p = Q.Head; Cài đặt: 40 Cài đặt: Danh sách liên kết while ( p != NULL ) { if ( p -> info ==k ) break; p = p -> next; } return p; } 41 c Duyệt danh sách Node *Search( LIST Q, Data k ) { Node *p; p = Q.Head; Cài đặt void Duyet_DS ( LIST Q) { Node *p; p = Q.Head; while ( p != NULL ) { p = p -> next; } } ! Là kỹ thuật để xét qua hết phần tử danh sách ! Thực – Khai báo trỏ p có kiểu Node – Cho trỏ p duyệt từ đầu đến cuối để qua phần tử Danh sách ! Thuật toán while (( p != NULL ) && (p -> info !=k )) p = p -> next; return p; } 42 Danh sách liên kết 43 Ví dụ: ! Viết # Các trường hợp • Hủy phần tử đầu • Hủy phần tử đứng sau phần tử q xác định • Hủy phần tử có giá trị xác định k hình ! Viết hàm in họ tên tsinh viên có điểm ! Viết hàm cho biết Họ tên Sv có ĐTB cao 45 Danh sách liên kết 44 d Hủy phần tử khỏi danh sách hàm in danh sách sinh viên Danh sách liên kết Danh sách liên kết Danh sách liên kết Hủy phần tử đầu danh sách: Q.Tail Q.Head Thuật toán: Nếu danh sách rỗng (khơng có phần tử đầu) => khơng thực xóa Nếu có phần tử đầu Lưu tạm thời phần tử đầu – lưu vào p Chuyển phần tử đầu sang phần tử Xóa phần tử đầu lưu tạm – xóa p Kiểm tra: Nếu danh sách có phần tử, xóa phần tử phần tử cuối khơng cịn # Chú ý: tạo nút dùng hàm cấp phát nhớ => Khi hủy phải dùng hàm để giải phóng nhớ 46 Danh sách liên kết 47 Danh sách liên kết Thuật toán: Hủy phần tử đứng sau phần tử q: # Thuật tốn # Nếu có phần tử q $ Lưu phần tử đứng sau phần tử q – lưu vào p $ Nếu có phần tử p (q phần tử cuôi) $ Tách phần tử p khỏi danh sách $ Nối phần tử q với phần tử sau p $ Giải phóng phần tử p Q.Head = Q.Head->Next 1f Q.Head 2f 2f 3f 3f 4f 4f … P P = Q.Head 48 Danh sách liên kết 49 Hủy phần tử có khóa k 2f 2f 3f 4f p = q->Next p 3f 4f 4f … q->Next = p->Next 50 Danh sách liên kết * Cài đặt: if (q != NULL) { if(p == Q.Tail) Q.Tail = q; q->next = p->next; delete p; } else //p phần tử đầu xâu { Q.Head = p -> next; if ( Q.Head == NULL) Q.Tail = NULL; } return 1; int RemoveNode( LIST &Q, Data k ) { NODE *p = Q.Head, *q = NULL; while( p != NULL) { if (p->info == k) break; q = p; p = p->next; } if (p == NULL) return 0; //Khơng tìm thấy k ! Thuật tốn: ! Bước 1: Tìm phần tử p có khóa k phần tử q đứng trước ! Bước Danh sách liên kết Q.Head q 1f 2: Nếu (p!= NULL) // tìm thấy k Hủy p khỏi xâu tương tự hủy phần tử sau q; Ngược lại Báo khơng có k; } 51 Danh sách liên kết 52 e Sắp xếp danh sách ! Để – Thay vị nội dung phần tử đổi mối liên kết phần tử Q.Head 4f 5f 5f Hoandoi(p->info,q->info); Q.Head 3f Danh sách liên kết 55 void ListSortInterchange( LIST &Q ) { Node *p, *q; //p q la hai bien dieu khien Data tg; for(p = Q.Head;p != NULL; p = p->next) for(q = p -> next;q!=NULL; q = q->next ) if ( p->info> q->info ) Q.Tail 4f Danh sách liên kết Cài đặt xếp danh sách cách thay đổi nội dung: # Là thực thay đổi trực tiếp thành phần infor nút thứ tự liên kết nút không thay đổi 3f 54 53 Hoán vị nội dung phần tử: xếp có hai phương án: – Hốn Danh sách liên kết } N Q.Tail 5f 4f 4f 5f N Danh sách liên kết 56 Danh sách liên kết Ví dụ Thay đổi mối liên kết ! Viết hàm xếp danh sách sinh viên theo thứ tự ĐTB tăng dần 57 Danh sách liên kết 58 void ListSortInterchange( LIST &Q ) { Node *p, *q; //p q la hai bien dieu khien Data tg; p = Q.Head; while ( p != NULL ) { q = p -> next; while( q != NULL ) { if ( p->info.DTB > q->info.TDB ) { tg = p->info; p->info = q->info; q->info = tg; } q = q->next; } p = p->next; } } Danh sách liên kết ! Là thực thay đổi trực tiếp thành phần Next nút " thứ tự liên kết nút thay đổi ! Ý tưởng: Tạo danh sách danh sách có thứ tự lấy từ danh sách cũ (đồng thời huỷ danh sách cũ ) 59 Danh sách liên kết Bài tập thực hành Q.Head 3f Q.Tail 4f 4f 5f 5f ! Thuật ! Cho thông tin cán gồm: mã cán bộ, họ tên, ngày sinh, hệ số lương, phụ cấp thành tiền (=hệ số lượng * 1050000 + phụ cấp) ! Viết chương trình quản lý cán dạng DSLK đơn, với yêu cầu: – Nhập vào danh sách cán – In lại ds cán có – Hủy bỏ cán đầu danh sách – Tìm kiếm cán có mã k – Sắp xếp DSCB theo thứ tự tăng dần thành tiền – Đếm số cán có lương triệu … toán xếp thay đổi mối liên kết : N – Bước Q.Head 3f Q.Head 3f 4f 5f Q.Tail N 5f 5f 5f 4f Q.Tail 4f 4f 1: Khởi tạo danh sách Result rỗng; 2: Tìm danh sách cũ Q (Head, Tail) phần tử phần tử nhỏ nhất; – Bước 3: Tách khỏi danh sách cũ Q (Head, Tail); – Bước 4: Chèn vào cuối danh sách Result; – Bước 5: Lặp lại bước chưa hết danh sách cũ Q (Head, Tail); – Bước 60 N Danh sách liên kết 61 Bài tập thực hành (y/c chi tiết) Nhập cán In cán Khởi tạo DSLK rỗng Tạo nút chứa cán Chèn thêm cán vào đầu DSLK đơn In DSCB Danh sách liên kết Tìm kiếm CB có mã Tính tổng lương CB Đếm số CB có lương từ đến triệu SX DSCB tăng dần theo tổng lương ! – Data: cấu trúc để mô tả thông tin lưu trữ nút – Linked: gồm hai trỏ để liên kết với phần tử trước phần tử sau danh sách Chèn thêm CB vào sau CB có mã x dụng CTC dạng menu lựa chọn: – 0 63 dụng yêu cầu Định nghĩa nút danh sách struct DNode { Data infor; //Khai báo thành phần liệu struct DNode *next; //khai báo liên kết sau struct DNode *previous; //khai báo liên kết trước }; ! Định nghĩa danh sách struct DLIST { DNode *Head; DNode *Tail; }; DLIST DQ; //Tạo danh sách kép lấy tên DQ DNode *new_element; 1. Khai báo CTDL: ! Mỗi Node gồm hai thành phần: Báo CTDL DSLK đơn chứa DS Cán gồm: MCB, Hoten, Tuoi, HSL, PC, TT(=HSL* 1.050.000 + PC) ! Định nghĩa CTC sau: Thoát – 1 Tạo DSCB – 3 Tìm kiếm CB theo mã – 5 Tính tổng lương cán ! Áp 62 III Danh sách liên kết kép ! Khai ! Áp Danh sách liên kết In lại DSCB Đếm số CB lương từ đến triệu … Danh sách liên kết Data 64 Data Data Danh sách liên kết 65 Danh sách liên kết * Ví dụ: struct SV { int MSV; char hoten[25]; float dtb; }; struct DNode { SV info; struct SV *next; struct SV *previous; }; DList DQ; MSV hoten next dtb previuos dtb next # Đối với danh sách kép có thao tác sau: • Tạo danh sách • Chèn phần tử • Hủy phần tử • Tìm kiếm phần tử • Duyệt danh sách • Sắp xếp danh sách theo thành phần liệu struct DList { DNode *Head; DNode *Tail; }; previuos previuos MSV hoten 66 – Khởi tạo danh sách rỗng – Tạo nút chứa thông tin cần lưu trữ next dtb Danh sách liên kết 67 Danh sách liên kết 68 Danh sách liên kết 72 Danh sách liên kết Chèn thêm phần tử vào danh sách: DNode *Get_Node( Data x ) { DNode *p; p = new DNode(); if (p == NULL) { printf(”Ko du bo nho”); exit(1); } p -> infor = x; p -> next = NULL; p -> previous = NULL; return p; } 70 ! Gồm: MSV hoten Thủ tục tạo nút ! Các trường hợp: – Chèn vào đầu danh sách vào cuối danh sách – Chèn vào sau phần tử q biết – Chèn vào trước phần tử q biết – Chèn Danh sách liên kết 71 Danh sách liên kết Cài đặt: Chèn thêm vào trước phần tử q: # Nếu phần tử q khác rỗng " có tồn phần tử q p = q -> previous //Tạo phần tử p đứng trước q new_element -> next = q new_element -> previous = p q -> previous = new_element 79 a Tạo danh sách Các thao danh sách kép Danh sách liên kết 80 void AddBefore(DLIST &DQ, DNode *q, DNode *new_element) { DNode *p = q -> previous; if ( q != NULL ) { new_element -> next = q; new_element -> previous = p; q -> previous = new_element; if (p != NULL) p -> next = new_element; if (q == DQ.Head) DQ.Head = new_element; } } Danh sách liên kết Hủy phần tử khỏi danh sách # Có trường hợp: • Hủy phần tử đầu • Hủy phần tử cuối • Hủy phần tử đứng sau phần tử q • Hủy phần tử đứng trước phần tử q • Hủy phần tử có khóa k 81 Danh sách liên kết Hủy phần tử đứng trước phần tử q: DQ.Head DQ.Tail A B C D p DQ.Tail A B DQ.Head A C q p B C C D DQ.Tail Danh sách liên kết 89 *Tìm kiếm phần tử có khóa xác định: phát từ đầu danh sách phát từ cuối danh sách Danh sách liên kết 90 ! Cho thông tin cán gồm: mã cán bộ, họ tên, ngày sinh, hệ số lương, phụ cấp thành tiền (=hệ số lượng * 1050000 + phụ cấp) ! Thực yêu cầu sau: – Áp dụng mảng Định nghĩa thao tác sau: ! In lại tồn danh sách cán ! Tính tổng lương tồn cán ! Đếm số CB có mức lương từ triệu đến triệu ! Tìm kiếm cán có mã ! SX DSCB tăng dần theo tổng lương – Viết 95 95 Danh sách liên kết Báo CTDL DSLK chứa Cán gồm: MCB, Hoten, Tuoi, HSL, PC, TT(=HSL* 1.050.000 + PC) ! Định nghĩa CTC sau: Nhập cán Tính tổng lương CB In cán SX DSCB tăng dần theo tổng lương Nhập DSCB In DS CB có tuổi 20 In DSCB Cho biết Họ tên CB có lương cao Tìm kiếm CB có mã Chèn thêm cán cvaof sau cán có mã x ! Áp dụng CTC dạng menu lựa chọn: Thoát – Tạo DSCB In lại DSCB – Tìm kiếm CB theo mã Đếm số CB lương từ đến triệu – Tính tổng lương cán … – Danh sách liên kết ! Cho thông tin Nhân viên gồm: mã nhân viên, họ tên, tuổi, HSL, PC (Luong = (HSL+PC)*1050000) ! Cài đặt CT ngôn ngữ C để quản lý DSNV dạng DSLK Đơn với yêu cầu sau: ! Đếm số CB có lương từ đến triệu 98 Danh sách liên kết Cài đặt chương trình Thơng tin nhân viên gồm: mã số nhân viên, họ tên, ngày sinh, tổng lương ! Thực yêu cầu sau: – a Khai báo CTDL DSLK đôi để quản lý DSNV – Thực thao tác danh sách ! b Thêm nhân viên vào đầu danh sách liên kết kép ! c In lại toàn danh sách nhân viên hình ! d Tính tổng lương tất nhân viên DS ! e Hủy nhân viên khỏi đầu danh sách ! f In danh sách nhân viên có mức lương cao ! g Sắp xếp DSNV theo tứ tự giảm dần lương ! Khai chương trình thực chức 96 *Bài tập áp dụng Bài tập thực hành (y/c chi tiết) Danh sách liên kết Bài tập áp dụng void Sort_Inter(D_LIST &DQ) { Dnode *p,*q; p = DQ.Head; q = p -> next; while (p!=NULL) { q = p -> next; while ( q != NULL) { if ( p -> info > q -> info ) Hoandoi( p->info , q->info ); q = q -> next; } p = p -> next; } } sách kép kết nối với phần tử trước sau nên, thực tìm kiếm cách: 93 Danh sách liên kết e Sắp xếp phần tử danh sách: ! danh – xuất B D 82 – xuất DQ.Tail A D void RemoveBefore (DLIST &DQ, Dnode *q) { Dnode *p; if ( q = = NULL ) MoveLast(DQ); else //Co phan tu q { if (q = = DQ.Head) //Phần tử q phần tử đầu { printf("\n Ko xoa duoc dang o vi tri dau"); exit(1); } p = q -> previous; //lay phan tu can huy bo q -> previous = p -> previous; if ( p = = DQ.Head ) DQ.Head = q; else p -> previous -> nex t = q; free(p); } } q DQ.Head DQ.Head 97 Cài đặt xóa phần tử đứng trước phần tử q 98 Danh sách liên kết – Tạo danh sách thêm vào danh sách số phần tử (đầu cuối) – Hiển thị lại toàn danh sách – Hiển thị ds cán có lương triệu – Tìm kiếm nhân viên theo mã – Chèn thêm nhân viên vào sau nhân viên q – Tính tổng lương nhân viên – Sắp xếp danh sách NV theo lương giảm dần – Chèn – … 99 ! Áp dụng chương trình menu lựa chọn 99 Danh sách liên kết Bài tập áp dụng Bài tập nhà – 6/10/2014 ! Cài đặt chương trình BTL dạng DSLK với số yêu cầu bản: – Tạo danh sách – Hiển thị tồn danh sách – Chèn đầu – Xóa đầu – Tìm kiếm – Sắp xếp ! Nộp – Hạn: Muộn 20h -ngày 30/1/2013 – Gửi mail: trinhxuan@gmail.com – subject: CTDL - CT6 - Họ tên sinh viên - Lớp – Đính kèm file ! File đặt theo nguyên tắc: Tên sinh viên_Lớp.CPP 10 Danh sách liên kết 10 Bài tập nhà buổi Đọc DS LK kép báo CTDL tạo danh sách ! Thêm phần tử ! Xóa ! Duyệt ! Sắp xếp 10 ! Ý ! Khởi ! Các nhóm chọn đối tượng cần quản lý toán ! Cài đặt quản lý đối tượng mảng, gồm tối thiểu: – Nhập & in DS - Tìm kiếm – Tính tổng & tính tổng có điều kiện - Sắp xếp – Đếm & đếm có điều kiện - Phần tử lớn nhỏ => Áp dụng yêu cầu ! Yêu cầu nộp bài: – Mỗi nhóm nộp bài, đầu chương trình ghi rõ thơng tin nhóm tốn – Gửi mail: trinhxuan@gmail.com trước 17h – ngày 12/10/2014 – Subject: CTDL – BTL – Mảng - – Tên file: CTDL_ Danh sách liên kết Bài tập nhà buổi Mỗi phần xác định: ! Khai Bài tập nhà buổi ! Mỗi Đọc Stack - Queue tưởng bước ! Minh họa ! Cài đặt ! Stack nghĩa đặt – Ứng dụng Danh sách liên kết 10 ! Queue – Định – Định – Cài – Cài nghĩa đặt – Ứng dụng Danh sách liên kết Đọc DS LK đơn báo CTDL tạo danh sách ! Thêm phần tử ! Xóa ! Duyệt ! Sắp xếp 10 Mỗi phần xác định: ! Khai ! Ý ! Khởi ! Các tưởng bước ! Minh họa ! Cài đặt Danh sách liên kết ... phần tử p Q.Head = Q.Head->Next 1f Q.Head 2f 2f 3f 3f 4f 4f … P P = Q.Head 48 Danh sách liên kết 49 Hủy phần tử có khóa k 2f 2f 3f 4f p = q->Next p 3f 4f 4f … q->Next = p->Next 50 Danh sách liên... while ( p != NULL ) { q = p -> next; while( q != NULL ) { if ( p->info.DTB > q->info.TDB ) { tg = p->info; p->info = q->info; q->info = tg; } q = q->next; } p = p->next; } } Danh sách liên kết... q = p -> next; while (p!=NULL) { q = p -> next; while ( q != NULL) { if ( p -> info > q -> info ) Hoandoi( p->info , q->info ); q = q -> next; } p = p -> next; } } sách kép kết nối với phần tử