Chapter_List
Download
Report
Transcript Chapter_List
Danh sách liên kết
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
1
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ố.
2
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ử ?
Xóa phần tử ?
3
Giới thiệu
Thực tế:
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.
4
Khái Niệm danh sách liên kế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ụ:
5
Các loại danh sách liên kế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.
6
Danh sách liên kết đơn
Mỗi phần tử có một liên kết đến phần tử phía
sau nó.
7
Danh sách liên kết kép
Mỗi phần tử có hai liên kế đến phần tử đứng
trước và sau nó.
8
Danh sách liên kết vò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.
9
Phần tử trên danh sách liên kết
Phần tử = dữ liệu + liên kết
10
Phần tử trên danh sách liên kết
11
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;
};
12
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;
};
13
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;
};
14
Cài đặt
Phần tử có dữ liệu gồm một cấu trúc
struct DATA
{
char name[50];
int id;
float number;
struct NODE
{
DATA data;
NODE *pNext;
};
};
15
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.
16
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:
17
Cấu tạo của danh sách liên kết
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
};
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
19
Signly linked list
head
data
link
…
Singly Linked List
List // Linked Implementation of List (for Singly Linked List)
head <pointer>
count <integer> // number of elements (optional).
End List
head
head
An empty Singly Linked List
having
only head.
20
count 0
An empty Singly Linked List
having head and count.
Các thao tác trên DSLK Đơn
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ử
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
21
Create an empty linked list
Before
head ?
After
head = NULL
head
List having head
head ?
count = ?
head
head = NULL
count = 0
List having head and count
22
count = 0
Create an empty linked list
23
Create an empty linked list
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
24
Create an empty linked list
Tạo lập danh sách rỗng
Count
list
?
pHead
?
Trước khi tạo lập
Count
list
pHead
0
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
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
25
Check linked list
Kiểm tra danh sách rỗng
int IsEmptyList(LIST L)
{
if(L.pHead == NULL)
return 1;
return 0;
}
Kiểm tra số phần tử trong danh sách
int CountNode(LIST L)
{
return L.Count;
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
26
Insert Node to a 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.
head
…
pNew
x
Otherwise: p is pPre->link, where pPre points to the predecessor of
the new node.
pNew
x
head
pPre
…
27
Insert Node to a Linked List
Update pointers:
3.
Point the new node to its successor.
Point the pointer p to the new node.
head
X
pNew->link = head
head= pNew
(1)
(2)
…
(2)
pNew
(1)
X
(2)
head
pNew
X
(1)
pNew->link = pPre->link (1)
pPre->link = pNew
(2)
pPre
X
…
28
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)
(2)
(a)
head
pNew
X
pNew->link = pPre->link (1)
pPre->link = pNew
(2)
pPre
X
(b)
(1)
…
pNew
x
head
pPre
…
30
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).
head
X
…
(a)
(2)
pNew
(1)
X
(b)
pNew->link = head (1)
head= pNew
(2)
head
pNew
head
pNew
31
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 inserted
Post 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 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
Thêm một node vào đầu danh sách
Trước khi thêm
(2)
pNew
Count
pHead
15
1
99
(1)
Sau khi thêm
Count
2
pHead
99
15
pNew
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
34
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)
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;
}
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
35
Các thao tác trên danh sách liên kết đơn
Thêm một nút vào đầu DS (quản lý bằng con trỏ đầu)
Cách 1.2
4/28/2020
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;
}
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
}
Đức Thắng
36
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 đầ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;
}
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
37
Các thao tác trên danh sách liên kết đơn
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
15
2
Count
99
pHead
pPrev
(2)
(1)
pNew
50
Sau khi thêm
Count
3
pHead
15
pPrev
4/28/2020
50
99
pNew
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
38
Các thao tác trên danh sách liên kết đơn
Thêm một nút vào giữa DS. Sau nút pRev(quản lý bằng con trỏ đầu )
Cách 1 void AddMid( LIST &L, NODE *pRev , NODE * pNew)
{
pNew pNext = pRev pNext;
pRev pNext = pNew;
Cách 2 }
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;
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
39
Các thao tác trên danh sách liên kết đơn
Thêm 1 nút vào giữa DS. Sau nút pRev(ql bằng con trỏ đầu và cuối )
Cách 1
void AddMid( LIST &L, NODE *pRev , NODE * pNew)
{
Cách 2
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;
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
4/28/2020 }
Đức Thắng
40
Các thao tác trên danh sách liên kết đơn
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
(2)
15
2
Count
99
50
(1)
pHead
pTail
pNew
L.pTail pNext = pNew
L.pTail = pNew
15
2
Count
99
50
pHead
pPrev
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
41
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.
head
pDel
…
Otherwise: p is pPre->link, where pPre points to the
predecessor of the node to be deleted.
head
pPre
pDel
…
42
Remove Node from
a Linked List (cont.)
2.
Update pointers: p points to the successor of the node to
be deleted.
head = pDel->link
head
X
Recycle pDel
pDel
…
pPre->link = pDel->link
head
pDel
pPre
Recycle pDel
X
3.
43
Recycle the memory of the deleted node.
…
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.
head
(a)
pPre->link = pDel->link
Recycle pDel
pDel
pPre
…
X
head
pPre
pDel
pPre
pDel
…
(b)
head
…
X
45
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)
head
X
pDel
…
(b)
head
head = pDel->link
pDel
46
Recycle pDel
head
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 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
Các thao tác trên danh sách liên kết đơn
Xóa một nút ở đầu DS
Trước khi xóa
(2)
15
2
Count
99
pHead
pCurr
(1)
L.pHead = pCurr pNext;
delete pCurr;
Sau khi xóa
99
1
Count
4/28/2020
pHead
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
49
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)
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;
}
}
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
4/28/2020
Đức Thắng
50
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;
}
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
4/28/2020
Đức Thắng
51
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
15
3
Count
50
99
pHead
pPrev
pCurr
pPrev pNext = pCurr pNext
Delete pCurr
Sau khi xóa
15
2
Count
99
pHead
pPrev
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
52
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)
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;
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
53
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;
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
54
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 --;
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
55
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;
}
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
56
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)
pCurr !=NULL
{
for(NODE * pCurr = L.pHead; pCur; pCurr pNext)
{
cout << pCurr data;
pCurr = pCurr pNext;
}
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
57
Các thao tác trên danh sách liên kết đơn
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)
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
58
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
}
4/28/2020
Bộ môn KHMT - Khoa CNTT - Trường ĐH Tôn
Đức Thắng
59