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 =pCurrpNext;
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