840 likes | 1.48k Views
Danh sách liên kết. Giới thiệu. 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ố. Giới thiệu. Đánh giá thao tác trên mảng :. Truy xuất phần tử ? Cập nhật ? Chèn phần tử ?
E N D
Giớithiệu Mảng: Cấutrúcdữliệuquenthuộ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ố.
Giớithiệu Đánhgiáthaotáctrênmảng: • Truy xuất phần tử ? • Cập nhật ? • Chèn phần tử ? • Xóa phần tử ?
Giớithiệu Thựctế: • 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. ?
KháiNiệmdanhsáchliênkết • 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ụ:
Cácloạidanhsáchliênkết • 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.
Danhsáchliênkếtđơn • Mỗi phần tử có một liên kết đến phần tử phía sau nó.
Danhsáchliênkếtkép • Mỗi phần tử có hai liên kế đến phần tử đứng trước và sau nó.
Danhsáchliênkếtvòng • 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.
Phầntửtrêndanhsáchliênkết • Phần tử = dữ liệu + liên kết
Càiđặt • Phần tử có dữ liệu gồm 1 thành phần • structNODE{ • dataType number;// dataType là kdl của number • NODE * pNext; • };
Càiđặt • Phần tử có dữ liệu gồm 3 thành phần • struct NODE • { • data type name; • datatypeid; • dataTypenumber; • NODE * pNext; • };
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]; • intid; • floatnumber; • NODE * pNext; • };
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; • intid; NODE *pNext; • floatnumber; }; • };
Tổchứcdanhsáchliênkết • Mỗidanhsáchliênkếtbaogồm: • Con trỏđếnphầntửđầu (hoặc/vàcuối ) danhsách • Con trỏđếnphầntửđầu: pHead • Con trỏđếnphầntửcuối: pTail • (Các) phầntửtrêndanhsách: • Dữliệu • Cácmốiliênkết • Lưu ý: pHead, pTailkhôngphảilàmộtnút, nó • chỉlà con trỏchỉđếnnút.
Tổchứcdanhsáchliênkết • Ví dụ: quản lý bằng con trỏ đầu: • Ví dụ quản lý bằng con trỏ đầu và cuối:
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 }; Cấutạocủadanhsáchliênkết Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
head … Signly linked list Singly Linked List data link List // Linked Implementation of List (for Singly Linked List) head <pointer> count <integer> // number of elements (optional). End List head count head 0 An empty Singly Linked List having only head. An empty Singly Linked List having head and count.
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ử Cácthaotáctrên DSLK Đơn Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
head head ? head = NULL head count = ? ? head count = 0 head = NULL count = 0 Create an empty linked list Before After List having head List having head and count
Create an empty linked list Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
Tạo lập danh sách rỗng Create an empty linked list Count pHead Count pHead list ? list ? 0 Trước khi tạo lập 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 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
Kiểm tra danh sách rỗng Kiểm tra số phần tử trong danh sách Check linked list int IsEmptyList(LIST L) { if(L.pHead == NULL) return 1; return 0; } int CountNode(LIST L) { return L.Count; } Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
head … Insert Node to a Linked List • Allocate memory for the new node and set up data. • 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. head … pNew x pNew x pPre
head … head … Insert Node to a Linked List • Update pointers: • Point the new node to its successor. • Point the pointer p to the new node. pNew->link = head (1) head= pNew (2) X (2) pNew (1) X pNew (2) (1) pNew->link = pPre->link (1) pPre->link = pNew (2) X pPre X
Insert Node to a Linked List (cont.) • Insertion is successful when allocation memory for the new node is successful.
head … Insert Node to a Linked List (cont.) • There is no difference between • insertion in the middle (a) and insertion at the endof the list (b) (a) (b) pNew (2) (1) pNew->link = pPre->link (1) pPre->link = pNew (2) X pPre X pNew x head pPre …
head … 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) X (2) pNew (1) X pNew->link = head (1) head= pNew (2) head head pNew pNew
Insert Algorithm <ErrorCode> Insert (valDataIn <DataType>) //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. Returnsuccess or overflow.
InsertNode Algorithm (cont.) <ErrorCode> Insert (valDataIn <dataType>) • Allocate pNew • if (memory overflow) • return overflow • else • pNew->data = DataIn • Locate pPre// pPre remains NULL if Insertion at the beginning or to an empty list • if (pPre = NULL) // Adding at the beginning or to an empty list • pNew->link = head • head = pNew • else// Adding in the middle or at the end of the list • pNew->link = pPre->link • pPre->link = pNew • return success end Insert
Trước khi thêm Sau khi thêm Thêmmột node vàođầudanhsách (2) pNew 99 (1) Count pHead 15 1 Count pHead 99 2 15 pNew Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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; } } Các thao tác trên danh sách liên kết đơn Cách 1 Cách 1.1 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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; } } Các thao tác trên danh sách liên kết đơn Cách 1.2 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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; } } Các thao tác trên danh sách liên kết đơn Cách 2 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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 Các thao tác trên danh sách liên kết đơn pNew pPrev pPrev 99 50 pNew Count pHead (2) (1) Count pHead 15 15 2 3 99 50 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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; } Các thao tác trên danh sách liên kết đơn Cách 1 Cách 2 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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; } Các thao tác trên danh sách liên kết đơn Cách 1 Cách 2 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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 Các thao tác trên danh sách liên kết đơn (2) Count pHead Count pHead pPrev pTail (1) pNew L.pTail pNext = pNew L.pTail = pNew 50 50 15 15 2 2 99 99 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
… Remove Node from a Linked List • Locate the pointer p in the listwhich 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. head pDel head pPre pDel …
head … Remove Node from a Linked List (cont.) • Update pointers: p points to the successor of the node to be deleted. • Recycle the memory of the deleted node. head = pDel->link Recycle pDel X pDel pPre->link = pDel->link Recycle pDel head pDel pPre X …
Remove Node from a Linked List (cont.) • Removal is successful when the node to be deleted is found.
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) pPre->link = pDel->link Recycle pDel head pDel pPre X … pDel pPre head … pDel pPre head X …
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) X pDel head= pDel->link Recycle pDel head head pDel pDel
RemoveNode Algorithm <ErrorCode> Remove (ref DataOut <DataType>) 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. Returnsuccess or failed.
RemoveNode Algorithm (cont.) <ErrorCode> Remove (ref DataOut <DataType>) • Allocate pPre, pDel// pPre remains NULL if the node to be deleted is at the beginning of the list or is the only node. • if (pDel is not found) • return failed • else • DataOut = pDel->data • if (pPre = NULL) // Remove the first node or the only node • head = pDel->link • else// Remove the node in the middle or at the end of the list • pPre->link = pDel->link • recycle pDel • return success end Remove
Xóa một nút ở đầu DS Trước khi xóa Sau khi xóa Các thao tác trên danh sách liên kết đơn (2) Count pHead Count pHead pCurr (1) • L.pHead = pCurr pNext; • delete pCurr; 15 99 2 1 99 Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng
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; } } Các thao tác trên danh sách liên kết đơn Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn Đức Thắng