Upload
elden
View
56
Download
3
Embed Size (px)
DESCRIPTION
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ử ? - PowerPoint PPT Presentation
Citation preview
Danh sách liên kết
1
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: pHeado Con trỏ đến phần tử cuối: pTail
(Các) phần tử trên danh sách:o Dữ liệuo 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
};
04/21/23 19Bộ 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 <pointer> count <integer> // 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ỗngKiểm tra danh sách rỗngKiểm tra số phần tử trong danh sáchThêm một nút vào danh sáchXóa một nút khỏi danh sáchDuyệt danh sáchTìm một phần tử
04/21/23 21Bộ 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 ? headhead = NULL
head
count = ?
? head
count = 0head = NULL count = 0
22
Create an empty linked list
23
Create an empty linked list
04/21/23 24Bộ 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
04/21/23 25Bộ 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
04/21/23 26Bộ 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
…
pNewx
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<ErrorCode> Insert (val DataIn <DataType>)// For ordered list.Inserts a new node in a singly linked list.
Pre DataIn contains data to be insertedPost If list is not full, DataIn has been inserted;
otherwise, list remains unchanged.Return success or overflow.
32
InsertNode Algorithm (cont.)<ErrorCode> Insert (val DataIn <dataType>)1. Allocate pNew2. if (memory overflow)
1. return overflow3. else
1. pNew->data = DataIn2. Locate pPre // pPre remains NULL if Insertion at the
beginning or to an empty list3. if (pPre = NULL) // Adding at the beginning or to an
empty list1. pNew->link = head2. head = pNew
4. else // Adding in the middle or at the end of the list1. pNew->link = pPre->link2. pPre->link = pNew
5. return successend Insert
33
Trước khi thêm
Sau khi thêm
04/21/23 34Bộ 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 = pNewNgượ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;
}
}
04/21/23 35Bộ 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;
}
}
04/21/23 36Bộ 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 = pNewNgượ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;
}
}
04/21/23 37Bộ 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
04/21/23 38Bộ 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;
}
04/21/23 39Bộ 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;
}
04/21/23 40Bộ 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
04/21/23 41Bộ 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 = pNewL.pTail = pNew
Remove Node from a Linked List1. 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
…
pDelX
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
pPrehead …
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
…
pDelX
head = pDel->link
Recycle 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.
Return success or failed.
47
RemoveNode Algorithm (cont.)<ErrorCode> Remove (ref DataOut <DataType>)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 failed3. else
1. DataOut = pDel->data2. if (pPre = NULL) // Remove the first node or the only node
1. head = pDel->link3. else // Remove the node in the middle or at the end of the
list1. pPre->link = pDel->link
4. recycle pDel5. return success
end Remove48
Xóa một nút ở đầu DS
Trước khi xóa
Sau khi xóa
04/21/23 49Bộ 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;
}
}
04/21/23 50Bộ 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ỗngVoid 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;
}
04/21/23 51Bộ 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
04/21/23 52Bộ 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 pNextDelete 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;
}
04/21/23 53Bộ 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;
}
04/21/23 54Bộ 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 =pCurrpNext;
delete pCurr;
L.count --;
}
04/21/23 55Bộ 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;
}
}
04/21/23 56Bộ 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;
}
}
04/21/23 57Bộ 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áchNếu gặp nút chứa khóa cần tìm Stop và
thông báo tìm thấyNếu đi đến cuối danh sách Stop và thông
báo không tìm thấyChi phí O(n)
04/21/23 58Bộ 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
}
04/21/23 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