Bài giảng Cấu trúc dữ liệu và Giải thuật - Danh sách liên kết - Phạm Ngọc Nam

1. Giới thiệu 2. Các loại danh sách liên kết 3. Các thao tác trên danh sách 4. So sánh các thực thi của danh sách 5. So sánh danh sách liên kết và mảng Mảng: Cấu trúc dữ liệu quen thuộc Tập có thứ tự.  Số lượng phần tử cố định (tĩnh).  Cấp phát vùng nhớ liên tục.  Truy xuất phần tử thông qua chỉ số.

pdf59 trang | Chia sẻ: candy98 | Lượt xem: 1150 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Bài giảng Cấu trúc dữ liệu và Giải thuật - Danh sách liên kết - Phạm Ngọc Nam, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Danh sách liên kết 1 Giới thiệu Các loại danh sách liên kết Các thao tác trên danh sách So sánh các thực thi của danh sách So sánh danh sách liên kết và mảng 2 Tập có thứ tự.  Số lượng phần tử cố định (tĩnh).  Cấp phát vùng nhớ liên tục.  Truy xuất phần tử thông qua chỉ số. Giới thiệu Mảng: Cấu trúc dữ liệu quen thuộc 3 Truy xuất phần tử ?  Cập nhật ?  Chèn phần tử ?  Xóa phần tử ? Giới thiệu Đánh giá thao tác trên mảng: 4 không xác định chính xác số lượng phần tử  Danh sách bệnh nhân tăng/giảm.  Danh sách sinh viên tăng/giảm  Vùng nhớ thay đổi trong quá trình sử dụng. Không đủ vùng nhớ cấp phát liên tục. Cấu trúc dữ liệu động đáp ứng nhu cầu trên. Giới thiệu Thực tế: ? 5 Danh sách liên kết là một tập dữ liệu tuần tự mà mỗi phần tử(element) chứa vị trí của phần tử tiếp theo.  element = data + link  Ví dụ: Khái Niệm danh sách liên kết 6 Danh sách liên kết đơn.  Danh sách liên kết kép.  Danh sách liên kết vòng. Các loại danh sách liên kết 7Mỗi phần tử có một liên kết đến phần tử phía sau nó. Danh sách liên kết đơn 8Mỗi phần tử có hai liên kế đến phần tử đứng trước và sau nó. Danh sách liên kết kép 9 Là danh sách liên kết đơn và có mối liên kết giữa phần tử cuối và phần tử đầu. Danh sách liên kết vòng 10  Phần tử = dữ liệu + liên kết  Phần tử trên danh sách liên kết 11 Phần tử trên danh sách liên kết 12 Cài đặt  Phần tử có dữ liệu gồm 1 thành phần struct NODE{ dataType number;// dataType là kdl của number NODE * pNext; }; 13 Cài đặt  Phần tử có dữ liệu gồm 3 thành phần struct NODE { data type name; datatype id; dataType number; NODE * pNext; }; 14 Cài đặt  Phần tử có dữ liệu gồm 3 thành phần Ví dụ name kiểu char, id kiểu int, number kiểu float, ta có cấu trúc như sau: struct NODE { char name[50]; int id; float number; NODE * pNext; }; 15 Cài đặt  Phần tử có dữ liệu gồm một cấu trúc struct DATA struct NODE { { char name[50]; DATA data; int id; NODE *pNext; float number; }; }; 16 Tổ chức danh sách liên kết Mỗi danh sách liên kết bao gồm:  Con trỏ đến phần tử đầu (hoặc/và cuối ) danh sách o Con trỏ đến phần tử đầu: pHead o Con trỏ đến phần tử cuối: pTail  (Các) phần tử trên danh sách: o Dữ liệu o Các mối liên kết  Lưu ý: pHead, pTail không phải là một nút, nó chỉ là con trỏ chỉ đến nút. 17 Tổ chức danh sách liên kết  Ví dụ: quản lý bằng con trỏ đầu:  Ví dụ quản lý bằng con trỏ đầu và cuối: 18 Cấu tạo của danh sách liên kết  Quản lý danh sách bằng con trỏ đầu struct LIST{ NODE *pHead; int Count; };  Quản lý danh sách bằng con trỏ đầu và cuối struct LIST{ NODE *pHead; NODE *pTail; int Count; // số nút trong danh sách có thể ko cần nếu ko dùng }; 11/1/2016 19 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Cấu tạo của danh sách liên kết List // Linked Implementation of List (for Singly Linked List) head count // number of elements (optional). End List Singly Linked List head head data link 20 head count An empty Singly Linked List having only head. An empty Singly Linked List having head and count. 0 Signly linked list  Tạo lập danh sách rỗng  Kiểm tra danh sách rỗng  Kiểm tra số phần tử trong danh sách  Thêm một nút vào danh sách  Xóa một nút khỏi danh sách  Duyệt danh sách  Tìm một phần tử 11/1/2016 21 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên DSLK Đơn Before After List having head List having head and count head ? head head = NULL head count = ? ? head count = 0 head = NULL count = 0 22 Create an empty linked list 23 Create an empty linked list 11/1/2016 24 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Create an empty linked list Tạo lập danh sách rỗng 11/1/2016 25 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng ? Count pHead ?list Trước khi tạo lập 0 Count pHead list Sau khi tạo lập void InitList(LIST &L) { L.Count = 0; L.pHead = NULL; } Lưu ý: Luôn luôn khởi tạo danh sách rỗng trước khi sử dụng Create an empty linked list Kiểm tra danh sách rỗng Kiểm tra số phần tử trong danh sách 11/1/2016 26 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng int IsEmptyList(LIST L) { if(L.pHead == NULL) return 1; return 0; } int CountNode(LIST L) { return L.Count; } Check linked list 1. Allocate memory for the new node and set up data. 2. Locate the pointer p in the list, which will point to the new node:  If the new node becomes the first element in the List: p is head.  Otherwise: p is pPre->link, where pPre points to the predecessor of the new node. 27 head pNew x pPre pNew head x Insert Node to a Linked List 3. Update pointers:  Point the new node to its successor.  Point the pointer p to the new node. 28 head X pNew X pNew->link = pPre->link (1) pPre->link = pNew (2) pPre (1)(2) pNew->link = head (1) head= pNew (2) X head pNew X (1) (2) Insert Node to a Linked List Insert Node to a Linked List (cont.) Insertion is successful when allocation memory for the new node is successful. 29 Insert Node to a Linked List (cont.) There is no difference between  insertion in the middle (a) and insertion at the end of the list (b) (a) (b) 30 head X pNew X pNew->link = pPre->link (1) pPre->link = pNew (2) pPre (1)(2) pPre pNew head x Insert Node to a Linked List (cont.) There is no difference between  insertion at the beginning of the list (a) and insertion to an empty list (b). (a) (b) 31 pNew head pNew pNew->link = head (1) head= pNew (2) X head pNew X (1) (2) head Insert Algorithm Insert (val DataIn ) // For ordered list. Inserts a new node in a singly linked list. Pre DataIn contains data to be inserted Post If list is not full, DataIn has been inserted; otherwise, list remains unchanged. Return success or overflow. 32 InsertNode Algorithm (cont.) Insert (val DataIn ) 1. Allocate pNew 2. if (memory overflow) 1. return overflow 3. else 1. pNew->data = DataIn 2. Locate pPre // pPre remains NULL if Insertion at the beginning or to an empty list 3. if (pPre = NULL) // Adding at the beginning or to an empty list 1. pNew->link = head 2. head = pNew 4. else // Adding in the middle or at the end of the list 1. pNew->link = pPre->link 2. pPre->link = pNew 5. return success end Insert 33  Trước khi thêm  Sau khi thêm 11/1/2016 34 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng 1 15 Count pHead 99 pNew (1) (2) pNew Count pHead 152 99 Thêm một node vào đầu danh sách  Thêm một nút vào đầu DS (quản lý bằng con trỏ đầu)  Nếu danh sách rỗng thì L.pHead = pNew  Ngược lại:  pNew  pNext = L.pHead  L.pHead = pNew void AddFirst( LIST &L , NODE * pNew){ if(L.pHead == NULL) L.pHead = pNew; else { pNew  pNext = L.pHead; L.pHead = pNew; } } 11/1/2016 35 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn Cách 1 Cách 1.1  Thêm một nút vào đầu DS (quản lý bằng con trỏ đầu) void AddFirst( LIST &L , datatype x) { NODE * pNew = new NODE; pNew data = x; pNew pNext = NULL; if(L.pHead == NULL) L.pHead = pNew; else { pNew  pNext = L.pHead; L.pHead = pNew; } }11/1/2016 36 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn Cách 1.2  Thêm một nút vào đầu DS (quản lý bằng con trỏ đầu và cuối)  Nếu danh sách rỗng thì L.pHead = L.pTail = pNew  Ngược lại:  pNew  pNext = L.pHead  L.pHead = pNew void AddFirst( LIST &L , NODE * pNew) { if(L.pHead == NULL) L.pHead = L.pTail = pNew; else { pNew  pNext = L.pHead; L.pHead = pNew; } } 11/1/2016 37 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn Cách 2  Thêm một nút vào giữa DS. Sau nút pRev (ql bằng con trỏ đầu)  Trước khi thêm  Sau khi thêm 11/1/2016 38 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn 992 15 50 pNew (1) pPrev (2) 503 15 99 pPrev pNew Count pHead Count pHead  Thêm một nút vào giữa DS. Sau nút pRev(quản lý bằng con trỏ đầu ) void AddMid( LIST &L, NODE *pRev , NODE * pNew) { pNew  pNext = pRev pNext; pRev pNext = pNew; } void AddMid( LIST &L , NODE *pRev , DataType x) { NODE *pNew = new NODE; pNew  data = x; pNew  pNext = NULL; pNew  pNext = pRev pNext; pRev pNext = pNew; } 11/1/2016 39 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn Cách 1 Cách 2  Thêm 1 nút vào giữa DS. Sau nút pRev(ql bằng con trỏ đầu và cuối ) void AddMid( LIST &L, NODE *pRev , NODE * pNew) { pNew  pNext = pRev pNext; pRev pNext = pNew; if(pRev == L.pTail) L.pTail = pNew; } void AddMid( LIST &L, NODE *pRev , Datatype x) { NODE *pNew = new NODE; pNew  data =x; pNew  pNext = NULL; pNew  pNext = pRev pNext; pRev pNext = pNew; if(pRev == L.pTail) L.pTail = pNew; }11/1/2016 40 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn Cách 1 Cách 2  Thêm 1 nút cuối DSLK  Nếu DS rỗng thì L.pHead = L.pTail = pNew  Ngược lại:  L.pTail  pNext = Pnew  L.pTail = pNew 11/1/2016 41 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn 992 15 pTail Count pHead 50 pNew (1) (2) 992 15 pPrev Count pHead 50 L.pTail  pNext = pNew L.pTail = pNew Remove Node from a Linked List 1. Locate the pointer p in the list which points to the node to be deleted (pDel will hold the node to be deleted).  If that node is the first element in the List: p is head.  Otherwise: p is pPre->link, where pPre points to the predecessor of the node to be deleted. 42 pPre pDel pDel head head Remove Node from a Linked List (cont.) 2. Update pointers: p points to the successor of the node to be deleted. 3. Recycle the memory of the deleted node. head pDel X head pDel X pPre head = pDel->link Recycle pDel pPre->link = pDel->link Recycle pDel 43 Remove Node from a Linked List (cont.) Removal is successful when the node to be deleted is found. 44 Remove Node from a Linked List (cont.) There is no difference between Removal a node from the middle (a) and removal a node from the end (b) of the list. (a) (b) 45 head pDel X pPre head pDelpPre pPre->link = pDel->link Recycle pDel pDel X pPre head Remove Node from a Linked List (cont.) There is no difference between  removal the node from the beginning (a) of the list and removal the only-remained node in the list (b). (a) (b) 46 head pDel head pDel head pDel X head = pDel->link Recycle pDel RemoveNode Algorithm Remove (ref DataOut ) Removes a node from a singly linked list. Pre DataOut contains the key need to be removed. Post If the key is found, DataOut will contain the data corresponding to it, and that node has been removed from the list; otherwise, list remains unchanged. Return success or failed. 47 RemoveNode Algorithm (cont.) Remove (ref DataOut ) 1. Allocate pPre, pDel // pPre remains NULL if the node to be deleted is at the beginning of the list or is the only node. 2. if (pDel is not found) 1. return failed 3. else 1. DataOut = pDel->data 2. if (pPre = NULL) // Remove the first node or the only node 1. head = pDel->link 3. else // Remove the node in the middle or at the end of the list 1. pPre->link = pDel->link 4. recycle pDel 5. return success end Remove 48  Xóa một nút ở đầu DS  Trước khi xóa  Sau khi xóa 11/1/2016 49 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn (1) 992 15 pCurr Count pHead 1 99 Count pHead (2) L.pHead = pCurr pNext; delete pCurr;  Xóa một nút ở đầu DS (ql bằng con trỏ đầu)  Nếu pHead != NULL thì  Lấy nút ở đầu DS (pCurr) ra để xóa  Tách pCurr ra khỏi danh sách  Delete pCurr Void DeleteFirst(LIST &L) { NODE *pCurr; if(L.pHead != NULL) { pCurr = L.pHead; L.pHead = L.pHead pNext;// L.pHead=pCurr->pNext delete pCurr; } } 11/1/2016 50 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn  Xóa một nút ở đầu DS (ql bằng con trỏ đầu và cuối)  Nếu pHead != NULL thì  Lấy nút ở đầu DS (pCurr) ra để xóa  Tách nút ở đầu DS (pCurr) ra khỏi danh sách  Delete pCurr  Nếu pHead = NULL thì pTail = NULL: Xâu rỗng Void DeleteFirst(LIST &L) { NODE *pCurr; if(L.pHead != NULL) { pCurr = L.pHead; L.pHead = L.pHead pNext; delete pCurr; } if(L.pHead == NULL) L.pTail = NULL; } 11/1/2016 51 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn  Xóa 1 nút ở giữa DS. Sau nút pRev (ql bằng con trỏ đầu)  Trước khi xóa  Sau khi xóa 11/1/2016 52 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn 503 15 99 pCurrpPrev 2 15 99 pPrev Count pHead Count pHead pPrev  pNext = pCurr  pNext Delete pCurr  Xóa 1 nút ở giữa DS. Sau nút pRev (ql bằng con trỏ đầu) Void DeleteAfter_pPrev(LIST & L, NODE * pPrev) { NODE * pCurr; pCurr = pPrev  pNext;// lấy nút sau pPrev ra để xóa pPrev  pNext =pCurr  pNext; delete pCurr; } 11/1/2016 53 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn  Xóa 1 nút ở giữa DS. Sau nút pRev (ql bằng con trỏ đầu và cuối) Int DeleteAfter_pPrev(LIST & L, NODE * pPrev) { NODE * pCurr; if(pPrev == L.pTail) return 0; pCurr = pPrev  pNext; pPrev  pNext =pCurr  pNext; delete pCurr; if(pPrev pNext == NULL) L.pTail = pPrev; } 11/1/2016 54 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn  Xóa 1 nút trong DS ( tổng quát)  void DeleteNode(LIST & L, NODE * pPrev, NODE * PCurr) { if(pPrev == NULL) // xóa nút đầu L.pHead =pCurr  pNext; else // Xóa nút giữa pPrev pNext =pCurrpNext; delete pCurr; L.count --; } 11/1/2016 55 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn  Duyệt DSLK Đơn: là đi từ đầu DSLK cho đến cuối DSLK  Để đi từ đầu DSLK đến cuối DSLK ta sử dụng một biến con trỏ NODE để lần lượt giữ địa chỉ các NODE trong DSLK. void PrintList( LIST L) { NODE * pCurr = L.pHead; while( pCurr != NULL) { cout << pCurr  data; pCurr = pCurr  pNext; } }11/1/2016 56 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn  Duyệt DSLK Đơn: sử dụng vòng lặp for void PrintList( LIST L) { for(NODE * pCurr = L.pHead; pCur; pCurr  pNext) { cout << pCurr  data; pCurr = pCurr  pNext; } } 11/1/2016 57 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn pCurr !=NULL  Tìm một phần tử  Duyệt tuần tự từ đầu danh sách  Nếu gặp nút chứa khóa cần tìm  Stop và thông báo tìm thấy  Nếu đi đến cuối danh sách  Stop và thông báo không tìm thấy  Chi phí O(n) 11/1/2016 58 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn o Tìm một phần tử NODE * FindNode(LIST L, DataType key ) { NODE * pCurr = L.pHead;// bđ từ đầu DS while(pCurr != NULL) { if(pCurr  data == key) return pCurr; // tìm Thấy pCurr = pCurr  pNext;// chuyển đến nút kế } return NULL;// không tìm thấy } 11/1/2016 59 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng Các thao tác trên danh sách liên kết đơn