SlideShare a Scribd company logo
CHAPTER 3: DANH SÁCH LIÊN KẾT
(LINKED LISTS)
Chương 3: Danh sách liên kết
Nội dung
 Giới thiệu
 Danh sách liên kết đơn (Single Linked List)
 Danh sách liên kết đôi (Double Linked List)
 Danh sách liên kết vòng (Circular Linked List)
2
Chương 3: Danh sách liên kết
Giới thiệu - Cấu trúc dữ liệu tĩnh
 Cấu trúc dữ liệu tĩnh:
 Khái niệm: Các đối tượng dữ liệu không thay đổi được kích
thước, cấu trúc, … trong suốt quá trình sống thuộc về kiểu dữ
liệu tĩnh
 Một số kiểu dữ liệu tĩnh: các cấu trúc dữ liệu được xây dựng từ
các kiểu cơ sở như: kiểu số thực, kiểu số nguyên, kiểu ký tự ...
hoặc từ các cấu trúc đơn giản như mẩu tin, tập hợp, mảng ...
3
Chương 3: Danh sách liên kết
Giới thiệu - Cấu trúc dữ liệu tĩnh
 Một số hạn chế của CTDL tĩnh:
 Một số đối tượng dữ liệu trong chu kỳ sống của nó có thể thay
đổi về cấu trúc, độ lớn,…
 Ví dụ như danh sách các học viên trong một lớp học có thể tăng
thêm, giảm đi ... Nếu dùng những cấu trúc dữ liệu tĩnh đã biết như
mảng để biểu diễn  Những thao tác phức tạp, kém tự nhiên 
chương trình khó đọc, khó bảo trì và nhất là khó có thể sử dụng bộ
nhớ một cách có hiệu quả
 Dữ liệu tĩnh sẽ chiếm vùng nhớ đã dành cho chúng suốt quá
trình hoạt động của chương trình  sử dụng bộ nhớ kém hiệu
quả
4
Chương 3: Danh sách liên kết
Giới thiệu – Ví dụ cấu trúc dữ liệu tĩnh
 Cấu trúc dữ liệu tĩnh: Ví dụ: Mảng 1 chiều
 Kích thước cố định (fixed size)
 Các phần tử tuần tự theo chỉ số 0 n-1
 Truy cập ngẫu nhiên (random access)
 Chèn 1 phần tử vào mảng, xóa 1 phần tử khỏi mảng tốn nhiều chi
phí
5
0 1 2 3 4 n-2 n-1
chèn
Chương 3: Danh sách liên kết
Giới thiệu - Cấu trúc dữ liệu động
 Cần xây dựng cấu trúc dữ liệu đáp ứng được các yêu cầu:
 Linh động hơn
 Có thể thay đổi kích thước, cấu trúc trong suốt thời gian sống
 Cấu trúc dữ liệu động
6
Chương 3: Danh sách liên kết
Giới thiệu - Cấu trúc dữ liệu động
 Cấu trúc dữ liệu động: Ví dụ: Danh sách liên kết, cây
 Cấp phát động lúc chạy chương trình
 Các phần tử nằm rải rác ở nhiều nơi trong bộ nhớ
 Kích thước danh sách chỉ bị giới hạn do RAM
 Tốn bộ nhớ hơn (vì phải chứa thêm vùng liên kết)
 Khó truy cập ngẫu nhiên
 Thao tác thêm, xoá đơn giản
7
Insert,
Delete
Chương 3: Danh sách liên kết
Giới thiệu - Danh sách liên kết
 Danh sách liên kết:
 Mỗi phần tử của danh sách gọi là node (nút)
 Mỗi node có 2 thành phần: phần dữ liệu và phần liên kết
(phần liên kết chứa địa chỉ của node kế tiếp hay node
trước nó)
 Các thao tác cơ bản trên danh sách liên kết:
 Thêm một phần tử mới
 Xóa một phần tử
 Tìm kiếm
 …
8
Chương 3: Danh sách liên kết
Giới thiệu - Danh sách liên kết
 Có nhiều kiểu tổ chức liên kết giữa các phần tử trong danh
sách như:
 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
9
Chương 3: Danh sách liên kết
Giới thiệu - Danh sách liên kết
 Danh sách liên kết đơn: mỗi phần tử liên kết với phần tử
đứng sau nó trong danh sách:
 Danh sách liên kết kép: mỗi phần tử liên kết với các phần
tử đứng trước và sau nó trong danh sách:
10
A B X Z Y
A B C D
Chương 3: Danh sách liên kết
Giới thiệu - Danh sách liên kết
11
 Danh sách liên kết vòng : phần tử cuối danh sách liên kết
với phần tử đầu danh sách:
A B X Z Y
A B C D
Chương 3: Danh sách liên kết
Nội dung
 Giới thiệu
 Danh sách liên kết đơn (Single Linked List)
 Danh sách liên kết kép (Doule Linked List)
 Danh sách liên kết vòng (Circular Linked List)
12
Chương 3: Danh sách liên kết
Danh sách liên kết đơn (DSLK đơn)
 Khai báo
 Các thao tác cơ bản trên DSLK đơn
 Sắp xếp trên DSLK đơn
13
Chương 3: Danh sách liên kết
DSLK đơn – Khai báo
 Là danh sách các node mà mỗi node có 2 thành phần:
 Thành phần dữ liệu: lưu trữ các thông tin về bản thân phần tử
 Thành phần mối liên kết: lưu trữ địa chỉ của phần tử kế tiếp trong
danh sách, hoặc lưu trữ giá trị NULL nếu là phần tử cuối danh
sách
 Khai báo node:
struct Node
{
DataType data; // DataType là kiểu đã định nghĩa trước
Node *pNext; // con trỏ chỉ đến cấu trúc Node
};
14
data
pNext
Node* tên_nút;
Chương 6: Danh sách liên kết
DSLK đơn – Khai báo
 Ví dụ 1: Khai báo node lưu số
nguyên:
struct Node
{
int data;
Node *pNext;
};
 Ví dụ 2: Khai báo node lưu
thông tin của một sinh viên:
struct SinhVien {
char Ten[30];
int MaSV;
};
struct Node {
SinhVien data;
Node *pNext;
};
15
Chương 3: Danh sách liên kết
DSLK đơn – Khai báo
 Tổ chức, quản lý:
 Để quản lý một DSLK đơn chỉ cần biết địa chỉ phần tử đầu
danh sách
 Con trỏ pHead sẽ được dùng để lưu trữ địa chỉ phần tử đầu
danh sách. Ta có khai báo:
Node *pHead;
 Để tiện lợi, có thể sử dụng thêm một con trỏ pTail giữ địa chỉ
phần tử cuối danh sách. Khai báo pTail như sau:
Node *pTail;
16
A B X Z Y
pHead
pTail
A
Chương 3: Danh sách liên kết
DSLK đơn – Khai báo
 Ví dụ: Khai báo cấu trúc 1 DSLK đơn chứa số nguyên
// kiểu của một phần tử trong danh sách
struct Node
{
int data;
Node* pNext;
};
// kiểu danh sách liên kết
struct List
{
Node* pHead;
Node* pTail;
};
17
Khai báo biến kiểu danh sách:
List tên_biến;
Chương 3: Danh sách liên kết
DSLK đơn – Khai báo
 Tạo một node mới
 Viết hàm getNode để tạo ra một nút cho danh sách với dữ
liệu là x
18
Node* getNode ( DataType x)
{
Node *p;
p = new Node; // Cấp phát vùng nhớ cho node
if (p==NULL)
{
cout<<“Khong du bo nho!”; return NULL;
}
p->data = x; // Gán dữ liệu cho phần tử p
p->pNext = NULL;
return p;
}
x
p
Chương 3: Danh sách liên kết
Danh sách liên kết đơn (DSLK đơn)
 Khai báo
 Các thao tác cơ bản trên DSLK đơn
 Sắp xếp trên DSLK đơn
19
Chương 3: Danh sách liên kết
DSLK đơn
 Các thao tác cơ bản
 Tạo danh sách rỗng
 Thêm một phần tử vào danh sách
 Duyệt danh sách
 Tìm kiếm
 Xóa một phần tử ra khỏi danh sách
 Hủy toàn bộ danh sách
 …
20
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Tạo danh sách rỗng
21
pHead
pTail
void Init(List &l)
{
l.pHead = l.pTail = NULL;
}
Chương 3: Danh sách liên kết
DSLK đơn
 Các thao tác cơ bản
 Tạo danh sách rỗng
 Thêm một phần tử vào danh sách
 Duyệt danh sách
 Tìm kiếm một giá trị trên danh sách
 Xóa một phần tử ra khỏi danh sách
 Hủy toàn bộ danh sách
 …
22
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử vào danh sách: Có 3 vị trí thêm
 Gắn vào đầu danh sách
 Gắn vào cuối danh sách
 Chèn vào sau nút q trong danh sách
 Chú ý trường hợp danh sách ban đầu rỗng
23
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử
 Nếu danh sách ban đầu rỗng
24
pHead
pTail
new_node
XpHead = pTail = new_node;
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử
 Gắn node vào đầu danh sách
25
A B C D E
pHead pTail
X
new_node
new_node->pNext = pHead;
pHead = new_node;
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Cài đặt: Gắn nút vào đầu DS
26
void addHead(List &l, Node* new_node)
{
if (l.pHead == NULL) // DS rỗng
{
l.pHead = l.pTail = new_node;
}
else
{
new_node->pNext = l.pHead;
l.pHead = new_node;
}
}
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Thuật toán: Thêm một thành phần dữ liệu vào đầu DS
// input: danh sách l
// output: danh sách l với phần tử chứa X ở đầu DS
 Nhập dữ liệu cho X (???)
 Tạo nút mới chứa dữ liệu X (???)
 Nếu tạo được:
 Gắn nút mới vào đầu danh sách (???)
27
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Ví dụ: Thêm một số nguyên vào đầu ds:
// Nhập dữ liệu cho X
int x;
cout<<“Nhap X=”;
cin>>x;
// Tạo nút mới
Node* new_node = getNode(x);
// Gắn nút vào đầu ds
if (new_node != NULL)
addHead(l, new_node);
28
43
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử vào danh sách: Có 3 vị trí thêm
 Gắn vào đầu danh sách
 Gắn vào cuối danh sách
 Chèn vào sau nút q trong danh sách
 Chú ý trường hợp danh sách ban đầu rỗng
29
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử
 Gắn node vào cuối danh sách:
30
A B C D E
pHead
pTail
X
new_node
pTail->pNext = new_node;
pTail = new_node;
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Cài đặt: Gắn nút vào cuối DS
31
void addTail(List &l, Node *new_node)
{
if (l.pHead == NULL)
{
l.pHead = l.pTail = new_node;
}
else
{
l.pTail->pNext = new_node;
l.pTail = new_node ;
}
}
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Ví dụ: Thêm một số nguyên vào cuối ds:
// Nhập dữ liệu cho X
int x;
cout<<“Nhập X=”;
cin>>x;
// Tạo nút mới
Node* p = getNode(x);
// Gắn nút vào cuối DS
if (p != NULL)
addTail(l, p);
32
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử vào danh sách: Có 3 vị trí thêm
 Gắn vào đầu danh sách
 Gắn vào cuối danh sách
 Chèn vào sau nút q trong danh sách
 Chú ý trường hợp danh sách ban đầu rỗng
33
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Thêm một phần tử
 Chèn một phần tử vào sau nút q
34
A B C D E
pHead
pTail
X
new_node
q
new_node -> pNext = q -> pNext;
q -> pNext = new_node ;
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Cài đặt: Chèn một phần tử vào sau nút q
35
void addAfter (List &l, Node *q, Node* new_node)
{
if (q!=NULL)
{
new_node->pNext = q->pNext;
q->pNext = new_node;
if (q==l.pTail)
l.pTail = new_node;
}
}
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Thuật toán: Thêm một thành phần dữ liệu vào sau q
// input: danh sách thành phần dữ liệu X
// output: danh sách với phần tử chứa X ở cuối DS
 Nhập dữ liệu cho nút q (???)
 Tìm nút q (???)
 Nếu tồn tại q trong ds thì:
 Nhập dữ liệu cho X (???)
 Tạo nút mới chứa dữ liệu X (???)
 Nếu tạo được:
 Gắn nút mới vào sau nút q (???)
 Ngược lại thì báo lỗi
36
Chương 3: Danh sách liên kết
DSLK đơn
 Các thao tác cơ bản
 Tạo danh sách rỗng
 Thêm một phần tử vào danh sách
 Duyệt danh sách
 Tìm kiếm một giá trị trên danh sách
 Xóa một phần tử ra khỏi danh sách
 Hủy toàn bộ danh sách
 …
37
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Duyệt danh sách
 Là thao tác thường được thực hiện khi có nhu cầu muốn lấy lần
lượt từng phần tử trong danh sách để xử lý, chẳng hạn xử lý:
 Xuất các phần tử trong danh sách
 Đếm các phần tử trong danh sách
 Tính tổng các phần tử trong danh sách
 Tìm tất cả các phần tử danh sách thoả điều kiện nào đó
 Hủy toàn bộ danh sách (và giải phóng bộ nhớ)
 …
38
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Duyệt danh sách
 Bước 1: p = pHead; //Cho p trỏ đến phần tử đầu danh sách
 Bước 2: Trong khi (chưa hết danh sách) thực hiện:
 B2.1 : Xử lý phần tử p
 B2.2 : p=p->pNext; // Cho p trỏ tới phần tử kế
39
Node *p = l.pHead;
while ( p!=NULL )
{
// xử lý cụ thể p tùy ứng dụng
p = p->pNext;
}
Chuyển
thành vòng
lặp for??
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Ví dụ: In các phần tử trong danh sách
40
void Output (List l)
{
Node* p=l.pHead;
while (p!=NULL)
{
cout<<p->data<<“t”;
p=p->pNext;
}
cout<<endl;
}
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Đếm số nút trong danh sách:
41
int CountNodes (List l)
{
int count = 0;
Node *p = l.pHead;
while (p!=NULL)
{
count++;
p = p->pNext;
}
return count;
}
Gọi hàm???
Chương 3: Danh sách liên kết
DSLK đơn
 Các thao tác cơ bản
 Tạo danh sách rỗng
 Thêm một phần tử vào danh sách
 Duyệt danh sách
 Tìm kiếm một giá trị trên danh sách
 Xóa một phần tử ra khỏi danh sách
 Hủy toàn bộ danh sách
 …
42
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
43
 Tìm kiếm một phần tử có khóa x
Node* Search (List l, int x)
{
Node* p = l.pHead;
while ( p!=NULL ) {
if ( p->data==x )
return p;
p=p->pNext;
}
return NULL;
}
Gọi hàm???
Chương 3: Danh sách liên kết
DSLK đơn
 Các thao tác cơ bản
 Tạo danh sách rỗng
 Thêm một phần tử vào danh sách
 Duyệt danh sách
 Tìm kiếm một giá trị trên danh sách
 Xóa một phần tử ra khỏi danh sách
 Hủy toàn bộ danh sách
 …
44
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Xóa một node của danh sách
 Xóa node đầu danh sách
 Xóa node sau node q trong danh sách
 Xóa node có khoá k
45
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Thuật toán: Xóa node đầu danh sách
 Bước 1: Nếu danh sách rỗng thì không xóa được và thoát
ct, ngược lại qua Bước 2
 Bước 2: Gọi p là node đầu của danh sách (p=pHead)
 Bước 3: Cho pHead trỏ vào node sau node p (pHead =p->pNext)
 Bước 4: Nếu không còn node nào thì pTail = NULL
 Bước 5: Giải phóng vùng nhớ mà p trỏ tới
46
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Minh họa: Xóa node đầu danh sách
47
A B C D E
pHead
pTail
p
pHead = p->pNext;
delete p;
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
// xóa được: hàm trả về 1
// xóa không được: hàm trả về 0
int removeHead (List &l){
if (l.pHead == NULL)
return 0;
Node* p=l.pHead;
l.pHead = p->pNext;
if (l.pHead == NULL) l.pTail=NULL; //Nếu danh sách rỗng
delete p;
return 1;
}
48
Cài đặt: Xóa node đầu danh sách
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Xóa một node của danh sách
 Xóa node đầu danh sách
 Xóa node sau node q trong danh sách
 Xóa node có khoá k
49
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Thuật toán: Xóa node sau node q trong danh sách:
 Điều kiện để có thể xóa được node sau q là:
 q phải khác NULL (q !=NULL)
 Node sau q phải khác NULL (q->pNext !=NULL)
 Thuật toán:
 Bước 1: Gọi p là node sau q
 Bước 2: Cho q trỏ vào node đứng sau p
 Bước 3: Nếu p là phần tử cuối thì pTail là q
 Bước 4: Giải phóng vùng nhớ mà p trỏ tới
50
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Minh họa: Xóa node sau node q trong danh sách
51
A B C D E
pHead
pTail
q p
q->pNext = p->pNext;
delete p;
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Cài đặt: Xóa node sau node q trong danh sách
52
// xóa được: hàm trả về 1
// xóa không được: hàm trả về 0
int removeAfter (List &l, Node* q ){
if (q !=NULL && q->pNext !=NULL) {
Node* p = q->pNext;
q->pNext = p->pNext;
if (p==l.pTail) l.pTail = q;
delete p;
return 1;
}
else return 0;
}
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Xóa một node của danh sách
 Xóa node đầu của danh sách
 Xóa node sau node q trong danh sách
 Xóa node có khoá k
53
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
Thuật toán: Xóa 1 node có khoá k
 Bước 1:
 Tìm node có khóa k (gọi là p) và node đứng trước nó (gọi
là q)
 Bước 2:
 Nếu (p!= NULL) thì // tìm thấy k
 Hủy p ra khỏi danh sách: tương tự hủy phần tử sau q
 Ngược lại
 Báo không có k
54
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Cài đặt:
Xóa 1
node có
khoá k
55
int removeNode (List &l, int k)
{
Node *p = l.pHead;
Node *q = NULL;
while (p != NULL)
{
if (p->data == k) break;
q = p;
p = p->pNext;
}
if (p == NULL) { cout<<“Không tìm thấy k”; return 0;}
else if (q == NULL)
// thực hiện xóa phần tử đầu ds là p
else
// thực hiện xóa phần tử p sau q
}
Tìm phần tử p có khóa k và
phần tử q đứng trước nó
A B C D E
pHead
pTail
Chương 3: Danh sách liên kết
DSLK đơn
 Các thao tác cơ bản
 Tạo danh sách rỗng
 Thêm một phần tử vào danh sách
 Duyệt danh sách
 Tìm kiếm một giá trị trên danh sách
 Xóa một phần tử ra khỏi danh sách
 Hủy toàn bộ danh sách
 …
56
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Hủy toàn bộ danh sách
 Để hủy toàn bộ danh sách, thao tác xử lý bao gồm hành động giải
phóng một phần tử, do vậy phải cập nhật các liên kết liên quan:
 Thuật toán:
 Bước 1: Trong khi (chưa hết danh sách) thực hiện:
 B1.1:
 p = pHead;
 pHead = pHead ->pNext; // Cho p trỏ tới phần tử kế
 B1.2:
 Hủy p;
 Bước 2:
 pTail = NULL; //Bảo đảm tính nhất quán khi xâu rỗng
57
Chương 3: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
 Cài đặt: Hủy toàn bộ danh sách
58
void RemoveList (List &l)
{
Node *p;
while (l.pHead!=NULL)
{
p = l.pHead;
l.pHead = p->pNext;
delete p;
}
l.pTail = NULL;
}
Gọi hàm???
Chương 3: Danh sách liên kết
Danh sách liên kết đơn (DSLK đơn)
 Khai báo
 Các thao tác cơ bản trên DSLK đơn
 Sắp xếp trên DSLK đơn
59
Chương 3: Danh sách liên kết
Sắp xếp trên DSLK đơn
 Các cách tiếp cận:
 Phương án 1: Hoán vị nội dung các phần tử trong danh
sách (thao tác trên vùng data)
 Sử dụng thêm vùng nhớ trung gian  thích hợp cho DSLK
với thành phần data có kích thước nhỏ
 Phương án 2: Thay đổi các mối liên kết (thao tác trên vùng
pNext)
 Phức tạp hơn
60
Chương 3: Danh sách liên kết
Sắp xếp trên DSLK đơn: Hoán vị data
 Cài đặt bằng pp đổi chỗ trực tiếp (Interchange Sort)
void InterChangeSort (List &l)
{
for (Node* p=l.pHead; p!=l.pTail; p=p->pNext)
for (Node* q=p->pNext; q!=NULL; q=q->pNext)
if (p->data > q->data)
Swap (p->data, q->data);
}
61
Chương 3: Danh sách liên kết
Sắp xếp trên DSLK đơn: Hoán vị data
62
12 2 8 1 5
p
q
l.pHead
l.pTail
Chương 3: Danh sách liên kết
Sắp xếp trên DSLK đơn: Hoán vị data
63
1 12 8 2 5
p
q
l.pHead
l.pTail
Chương 3: Danh sách liên kết
64
1 2 12 8 5
p
q
l.pHead
l.pTail
Sắp xếp trên DSLK đơn: Hoán vị data
Chương 3: Danh sách liên kết
65
1 2 5 12 8
p
q
l.pHead
l.pTail
Sắp xếp trên DSLK đơn: Hoán vị data
Chương 3: Danh sách liên kết
66
1 2 5 8 12
p
q
ng
l.pHead
l.pTail
Sắp xếp trên DSLK đơn: Hoán vị data
Chương 3: Danh sách liên kết
Sắp xếp bằng pp chọn trực tiếp
(Selection sort)
void ListSelectionSort (List &l)
{
for ( Node* p = l.pHead ; p != l.pTail ; p = p->pNext )
{
Node* min = p;
for ( Node* q = p-> pNext; q != NULL ; q = q-> pNext )
if ( min->data > q->data ) min = q ;
Swap(min->data, p->data);
}
}
67
Chương 3: Danh sách liên kết
Sắp xếp trên DSLK đơn: Thay đổi liên kết
 Một trong những cách thay đổi liên kết đơn giản nhất là
tạo một danh sách mới là danh sách có thứ tự từ danh
sách cũ (GT.101)
 Bước 1: Khởi tạo danh sách mới Result là rỗng;
 Bước 2: Tìm phần tử nhỏ nhất min trong danh sách cũ l;
 Bước 3: Tách min khỏi danh sách l;
 Bước 4: Chèn min vào cuối danh sách Result;
 Bước 5: Lặp lại bước 2 khi chưa hết danh sách cũ l;
68
69
void SortList( List &l ){
List lResult;
Init( lResult );
Node *p,*q, *min, *minprev;
while( l.pHead != NULL ){
min = l.pHead;
q = min->pNext;
p = l.pHead;
minprev = NULL;
while ( q != NULL )
{
if (min->data >q->data ) {
min = q;
minprev = p;
}
p = q;
q = q->pNext;
}
if ( minprev != NULL )
minprev->pNext = min->pNext;
else
l.pHead = min->pNext;
min->pNext = NULL;
addTail( lResult, min );
}
l = lResult;
}
5 4 3 9
minminprev

More Related Content

PDF
Chuong 2. cnpm
PDF
Luận văn: Nhận dạng và phân loại hoa quả trong ảnh màu, HAY
PPT
Chuong 2 - CSDL phân tán
PPT
Danh Sach Lien Ket
PDF
Giới thiệu cơ bản về Big Data và các ứng dụng thực tiễn
PDF
Lập trình ứng dụng web asp.net với C# - tailieumienphi.edu.vn
DOCX
Báo cáo môn đảm bảo chất lượng phần mềm
DOC
Hệ PhâN TáN
 
Chuong 2. cnpm
Luận văn: Nhận dạng và phân loại hoa quả trong ảnh màu, HAY
Chuong 2 - CSDL phân tán
Danh Sach Lien Ket
Giới thiệu cơ bản về Big Data và các ứng dụng thực tiễn
Lập trình ứng dụng web asp.net với C# - tailieumienphi.edu.vn
Báo cáo môn đảm bảo chất lượng phần mềm
Hệ PhâN TáN
 

What's hot (20)

PDF
Luận văn: Xây dựng website cho công ty truyền thông, HOT
DOC
Luận văn Thạc sĩ xây dựng website thương mại điện tử, áp dụng cho bán sách tr...
DOCX
Bao cao UML phan tich he thong nha cho thue
DOCX
Báo cáo môn mã nguồn mở
PDF
Giải pháp xử lý big data trên apache spark
DOC
Đồ án tốt nghiệp Xây dựng ứng dụng fastfood trên nền android
PDF
Hệ thống giám sát chỉ số môi trường và hiển thị thông tin trên Web
PDF
Hỗ trợ ra quyết định
PDF
Heap Sort
PPTX
Slide Báo Cáo Đồ Án Tốt Nghiệp CNTT
DOCX
Báo cáo đồ án - Thiết kế web tại Thanh Hóa
DOC
Luận văn Thạc sĩ Nghiên cứu triển khai giải pháp đảm bảo an ninh mạng trên nề...
PDF
Báo cáo Quản lý dự án phần mềm PTIT
DOC
Đề tài: Xây dựng website bán hàng trực tuyến, HAY
PDF
Phân tích cảm xúc trong tiếng việt bằng phương pháp máy học.pdf
PDF
Baitap uml mau_thầy trung
PDF
Đề Tài Thiết Kế Phần Mềm Quản Lý Sinh Viên
DOC
Luận văn Thạc sĩ Xây dựng ứng dụng phát hiện khuôn mặt trong ảnh sử dụng opencv
PDF
Báo Cáo Cuối Ký Thực Tập Tốt Nghiệp Xậy Dựng Web Bán Hàng Trực Tuyến bằng Ope...
DOC
Đồ Án Tốt Nghiệp công Nghệ Thông Tin.doc
Luận văn: Xây dựng website cho công ty truyền thông, HOT
Luận văn Thạc sĩ xây dựng website thương mại điện tử, áp dụng cho bán sách tr...
Bao cao UML phan tich he thong nha cho thue
Báo cáo môn mã nguồn mở
Giải pháp xử lý big data trên apache spark
Đồ án tốt nghiệp Xây dựng ứng dụng fastfood trên nền android
Hệ thống giám sát chỉ số môi trường và hiển thị thông tin trên Web
Hỗ trợ ra quyết định
Heap Sort
Slide Báo Cáo Đồ Án Tốt Nghiệp CNTT
Báo cáo đồ án - Thiết kế web tại Thanh Hóa
Luận văn Thạc sĩ Nghiên cứu triển khai giải pháp đảm bảo an ninh mạng trên nề...
Báo cáo Quản lý dự án phần mềm PTIT
Đề tài: Xây dựng website bán hàng trực tuyến, HAY
Phân tích cảm xúc trong tiếng việt bằng phương pháp máy học.pdf
Baitap uml mau_thầy trung
Đề Tài Thiết Kế Phần Mềm Quản Lý Sinh Viên
Luận văn Thạc sĩ Xây dựng ứng dụng phát hiện khuôn mặt trong ảnh sử dụng opencv
Báo Cáo Cuối Ký Thực Tập Tốt Nghiệp Xậy Dựng Web Bán Hàng Trực Tuyến bằng Ope...
Đồ Án Tốt Nghiệp công Nghệ Thông Tin.doc
Ad

Viewers also liked (8)

DOC
Ky thuatkhudequy
PDF
CTDL&GT: Các loại danh sách liên kết
PDF
Programming technique 1_2_7921
PDF
Giao trinh ky thuat lap trinh 2
PDF
Cach giai bai tap ham de quy minh tim duoc
PDF
Chuong 2. de quy dai hoc
PPT
Chuong 05 de quy
PDF
Bài 7: Danh sách liên kết (LINKED LIST) và tập hợp (SET) - Giáo trình FPT
Ky thuatkhudequy
CTDL&GT: Các loại danh sách liên kết
Programming technique 1_2_7921
Giao trinh ky thuat lap trinh 2
Cach giai bai tap ham de quy minh tim duoc
Chuong 2. de quy dai hoc
Chuong 05 de quy
Bài 7: Danh sách liên kết (LINKED LIST) và tập hợp (SET) - Giáo trình FPT
Ad

Similar to C3 danh sachlienket (20)

PDF
C5 danhsachlienket
PPTX
Cấu Trúc Dữ Liệu_Baigiang4_Danh sách liên kết.pptx
PPTX
Danh sách liên kết là 1 cấu trúc dữ liệu được sử dụng để lưu trữ 1 tập hợp cá...
PDF
Cau truc dl_va_giai_thuat_bai1[1] - copy
PDF
Cấu trúc dữ liệu kiểu danh sách liên kết
PDF
Cấu trúc dữ liệu danh sách liên kết (Linked List) - VietTuts.pdf
DOC
Bài tập CTDL và GT 5
PDF
Cấu trúc dữ liệu cơ bản 2
PDF
Cấu trúc dữ liệu danh sách liên kết đôi (Doubly Linked List) - VietTuts.pdf
PDF
cau-truc-du-lieu-va-giai-thuat_pham-the-bao_slides---danh-sach.pdf
PDF
ctdl&amp;gt 04-list_don
PDF
CHƯƠNG 3.pdf
PPT
C3 stack queue
PPTX
Giới thiệu Đại số quan hệ Phép toán tập hợp Phép chọn Phép chiếu Phép tích Ca...
PDF
Chuong 4-Thiet ke du lieu.pdf
PPT
Thuật toán Brich , Khai phá dữ liệu
PDF
Cấu trúc dữ liệu danh sách liên kết vòng (Circular Linked List) - VietTuts.pdf
PPT
BáO CáO Lý ThuyếT Java
PPT
Ctdl c4-cay
PPT
Ctdl c4-cay
C5 danhsachlienket
Cấu Trúc Dữ Liệu_Baigiang4_Danh sách liên kết.pptx
Danh sách liên kết là 1 cấu trúc dữ liệu được sử dụng để lưu trữ 1 tập hợp cá...
Cau truc dl_va_giai_thuat_bai1[1] - copy
Cấu trúc dữ liệu kiểu danh sách liên kết
Cấu trúc dữ liệu danh sách liên kết (Linked List) - VietTuts.pdf
Bài tập CTDL và GT 5
Cấu trúc dữ liệu cơ bản 2
Cấu trúc dữ liệu danh sách liên kết đôi (Doubly Linked List) - VietTuts.pdf
cau-truc-du-lieu-va-giai-thuat_pham-the-bao_slides---danh-sach.pdf
ctdl&amp;gt 04-list_don
CHƯƠNG 3.pdf
C3 stack queue
Giới thiệu Đại số quan hệ Phép toán tập hợp Phép chọn Phép chiếu Phép tích Ca...
Chuong 4-Thiet ke du lieu.pdf
Thuật toán Brich , Khai phá dữ liệu
Cấu trúc dữ liệu danh sách liên kết vòng (Circular Linked List) - VietTuts.pdf
BáO CáO Lý ThuyếT Java
Ctdl c4-cay
Ctdl c4-cay

C3 danh sachlienket

  • 1. CHAPTER 3: DANH SÁCH LIÊN KẾT (LINKED LISTS)
  • 2. Chương 3: Danh sách liên kết Nội dung  Giới thiệu  Danh sách liên kết đơn (Single Linked List)  Danh sách liên kết đôi (Double Linked List)  Danh sách liên kết vòng (Circular Linked List) 2
  • 3. Chương 3: Danh sách liên kết Giới thiệu - Cấu trúc dữ liệu tĩnh  Cấu trúc dữ liệu tĩnh:  Khái niệm: Các đối tượng dữ liệu không thay đổi được kích thước, cấu trúc, … trong suốt quá trình sống thuộc về kiểu dữ liệu tĩnh  Một số kiểu dữ liệu tĩnh: các cấu trúc dữ liệu được xây dựng từ các kiểu cơ sở như: kiểu số thực, kiểu số nguyên, kiểu ký tự ... hoặc từ các cấu trúc đơn giản như mẩu tin, tập hợp, mảng ... 3
  • 4. Chương 3: Danh sách liên kết Giới thiệu - Cấu trúc dữ liệu tĩnh  Một số hạn chế của CTDL tĩnh:  Một số đối tượng dữ liệu trong chu kỳ sống của nó có thể thay đổi về cấu trúc, độ lớn,…  Ví dụ như danh sách các học viên trong một lớp học có thể tăng thêm, giảm đi ... Nếu dùng những cấu trúc dữ liệu tĩnh đã biết như mảng để biểu diễn  Những thao tác phức tạp, kém tự nhiên  chương trình khó đọc, khó bảo trì và nhất là khó có thể sử dụng bộ nhớ một cách có hiệu quả  Dữ liệu tĩnh sẽ chiếm vùng nhớ đã dành cho chúng suốt quá trình hoạt động của chương trình  sử dụng bộ nhớ kém hiệu quả 4
  • 5. Chương 3: Danh sách liên kết Giới thiệu – Ví dụ cấu trúc dữ liệu tĩnh  Cấu trúc dữ liệu tĩnh: Ví dụ: Mảng 1 chiều  Kích thước cố định (fixed size)  Các phần tử tuần tự theo chỉ số 0 n-1  Truy cập ngẫu nhiên (random access)  Chèn 1 phần tử vào mảng, xóa 1 phần tử khỏi mảng tốn nhiều chi phí 5 0 1 2 3 4 n-2 n-1 chèn
  • 6. Chương 3: Danh sách liên kết Giới thiệu - Cấu trúc dữ liệu động  Cần xây dựng cấu trúc dữ liệu đáp ứng được các yêu cầu:  Linh động hơn  Có thể thay đổi kích thước, cấu trúc trong suốt thời gian sống  Cấu trúc dữ liệu động 6
  • 7. Chương 3: Danh sách liên kết Giới thiệu - Cấu trúc dữ liệu động  Cấu trúc dữ liệu động: Ví dụ: Danh sách liên kết, cây  Cấp phát động lúc chạy chương trình  Các phần tử nằm rải rác ở nhiều nơi trong bộ nhớ  Kích thước danh sách chỉ bị giới hạn do RAM  Tốn bộ nhớ hơn (vì phải chứa thêm vùng liên kết)  Khó truy cập ngẫu nhiên  Thao tác thêm, xoá đơn giản 7 Insert, Delete
  • 8. Chương 3: Danh sách liên kết Giới thiệu - Danh sách liên kết  Danh sách liên kết:  Mỗi phần tử của danh sách gọi là node (nút)  Mỗi node có 2 thành phần: phần dữ liệu và phần liên kết (phần liên kết chứa địa chỉ của node kế tiếp hay node trước nó)  Các thao tác cơ bản trên danh sách liên kết:  Thêm một phần tử mới  Xóa một phần tử  Tìm kiếm  … 8
  • 9. Chương 3: Danh sách liên kết Giới thiệu - Danh sách liên kết  Có nhiều kiểu tổ chức liên kết giữa các phần tử trong danh sách như:  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 9
  • 10. Chương 3: Danh sách liên kết Giới thiệu - Danh sách liên kết  Danh sách liên kết đơn: mỗi phần tử liên kết với phần tử đứng sau nó trong danh sách:  Danh sách liên kết kép: mỗi phần tử liên kết với các phần tử đứng trước và sau nó trong danh sách: 10 A B X Z Y A B C D
  • 11. Chương 3: Danh sách liên kết Giới thiệu - Danh sách liên kết 11  Danh sách liên kết vòng : phần tử cuối danh sách liên kết với phần tử đầu danh sách: A B X Z Y A B C D
  • 12. Chương 3: Danh sách liên kết Nội dung  Giới thiệu  Danh sách liên kết đơn (Single Linked List)  Danh sách liên kết kép (Doule Linked List)  Danh sách liên kết vòng (Circular Linked List) 12
  • 13. Chương 3: Danh sách liên kết Danh sách liên kết đơn (DSLK đơn)  Khai báo  Các thao tác cơ bản trên DSLK đơn  Sắp xếp trên DSLK đơn 13
  • 14. Chương 3: Danh sách liên kết DSLK đơn – Khai báo  Là danh sách các node mà mỗi node có 2 thành phần:  Thành phần dữ liệu: lưu trữ các thông tin về bản thân phần tử  Thành phần mối liên kết: lưu trữ địa chỉ của phần tử kế tiếp trong danh sách, hoặc lưu trữ giá trị NULL nếu là phần tử cuối danh sách  Khai báo node: struct Node { DataType data; // DataType là kiểu đã định nghĩa trước Node *pNext; // con trỏ chỉ đến cấu trúc Node }; 14 data pNext Node* tên_nút;
  • 15. Chương 6: Danh sách liên kết DSLK đơn – Khai báo  Ví dụ 1: Khai báo node lưu số nguyên: struct Node { int data; Node *pNext; };  Ví dụ 2: Khai báo node lưu thông tin của một sinh viên: struct SinhVien { char Ten[30]; int MaSV; }; struct Node { SinhVien data; Node *pNext; }; 15
  • 16. Chương 3: Danh sách liên kết DSLK đơn – Khai báo  Tổ chức, quản lý:  Để quản lý một DSLK đơn chỉ cần biết địa chỉ phần tử đầu danh sách  Con trỏ pHead sẽ được dùng để lưu trữ địa chỉ phần tử đầu danh sách. Ta có khai báo: Node *pHead;  Để tiện lợi, có thể sử dụng thêm một con trỏ pTail giữ địa chỉ phần tử cuối danh sách. Khai báo pTail như sau: Node *pTail; 16 A B X Z Y pHead pTail A
  • 17. Chương 3: Danh sách liên kết DSLK đơn – Khai báo  Ví dụ: Khai báo cấu trúc 1 DSLK đơn chứa số nguyên // kiểu của một phần tử trong danh sách struct Node { int data; Node* pNext; }; // kiểu danh sách liên kết struct List { Node* pHead; Node* pTail; }; 17 Khai báo biến kiểu danh sách: List tên_biến;
  • 18. Chương 3: Danh sách liên kết DSLK đơn – Khai báo  Tạo một node mới  Viết hàm getNode để tạo ra một nút cho danh sách với dữ liệu là x 18 Node* getNode ( DataType x) { Node *p; p = new Node; // Cấp phát vùng nhớ cho node if (p==NULL) { cout<<“Khong du bo nho!”; return NULL; } p->data = x; // Gán dữ liệu cho phần tử p p->pNext = NULL; return p; } x p
  • 19. Chương 3: Danh sách liên kết Danh sách liên kết đơn (DSLK đơn)  Khai báo  Các thao tác cơ bản trên DSLK đơn  Sắp xếp trên DSLK đơn 19
  • 20. Chương 3: Danh sách liên kết DSLK đơn  Các thao tác cơ bản  Tạo danh sách rỗng  Thêm một phần tử vào danh sách  Duyệt danh sách  Tìm kiếm  Xóa một phần tử ra khỏi danh sách  Hủy toàn bộ danh sách  … 20
  • 21. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Tạo danh sách rỗng 21 pHead pTail void Init(List &l) { l.pHead = l.pTail = NULL; }
  • 22. Chương 3: Danh sách liên kết DSLK đơn  Các thao tác cơ bản  Tạo danh sách rỗng  Thêm một phần tử vào danh sách  Duyệt danh sách  Tìm kiếm một giá trị trên danh sách  Xóa một phần tử ra khỏi danh sách  Hủy toàn bộ danh sách  … 22
  • 23. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử vào danh sách: Có 3 vị trí thêm  Gắn vào đầu danh sách  Gắn vào cuối danh sách  Chèn vào sau nút q trong danh sách  Chú ý trường hợp danh sách ban đầu rỗng 23
  • 24. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử  Nếu danh sách ban đầu rỗng 24 pHead pTail new_node XpHead = pTail = new_node;
  • 25. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử  Gắn node vào đầu danh sách 25 A B C D E pHead pTail X new_node new_node->pNext = pHead; pHead = new_node;
  • 26. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Cài đặt: Gắn nút vào đầu DS 26 void addHead(List &l, Node* new_node) { if (l.pHead == NULL) // DS rỗng { l.pHead = l.pTail = new_node; } else { new_node->pNext = l.pHead; l.pHead = new_node; } }
  • 27. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Thuật toán: Thêm một thành phần dữ liệu vào đầu DS // input: danh sách l // output: danh sách l với phần tử chứa X ở đầu DS  Nhập dữ liệu cho X (???)  Tạo nút mới chứa dữ liệu X (???)  Nếu tạo được:  Gắn nút mới vào đầu danh sách (???) 27
  • 28. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Ví dụ: Thêm một số nguyên vào đầu ds: // Nhập dữ liệu cho X int x; cout<<“Nhap X=”; cin>>x; // Tạo nút mới Node* new_node = getNode(x); // Gắn nút vào đầu ds if (new_node != NULL) addHead(l, new_node); 28 43
  • 29. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử vào danh sách: Có 3 vị trí thêm  Gắn vào đầu danh sách  Gắn vào cuối danh sách  Chèn vào sau nút q trong danh sách  Chú ý trường hợp danh sách ban đầu rỗng 29
  • 30. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử  Gắn node vào cuối danh sách: 30 A B C D E pHead pTail X new_node pTail->pNext = new_node; pTail = new_node;
  • 31. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Cài đặt: Gắn nút vào cuối DS 31 void addTail(List &l, Node *new_node) { if (l.pHead == NULL) { l.pHead = l.pTail = new_node; } else { l.pTail->pNext = new_node; l.pTail = new_node ; } }
  • 32. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Ví dụ: Thêm một số nguyên vào cuối ds: // Nhập dữ liệu cho X int x; cout<<“Nhập X=”; cin>>x; // Tạo nút mới Node* p = getNode(x); // Gắn nút vào cuối DS if (p != NULL) addTail(l, p); 32
  • 33. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử vào danh sách: Có 3 vị trí thêm  Gắn vào đầu danh sách  Gắn vào cuối danh sách  Chèn vào sau nút q trong danh sách  Chú ý trường hợp danh sách ban đầu rỗng 33
  • 34. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Thêm một phần tử  Chèn một phần tử vào sau nút q 34 A B C D E pHead pTail X new_node q new_node -> pNext = q -> pNext; q -> pNext = new_node ;
  • 35. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Cài đặt: Chèn một phần tử vào sau nút q 35 void addAfter (List &l, Node *q, Node* new_node) { if (q!=NULL) { new_node->pNext = q->pNext; q->pNext = new_node; if (q==l.pTail) l.pTail = new_node; } }
  • 36. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Thuật toán: Thêm một thành phần dữ liệu vào sau q // input: danh sách thành phần dữ liệu X // output: danh sách với phần tử chứa X ở cuối DS  Nhập dữ liệu cho nút q (???)  Tìm nút q (???)  Nếu tồn tại q trong ds thì:  Nhập dữ liệu cho X (???)  Tạo nút mới chứa dữ liệu X (???)  Nếu tạo được:  Gắn nút mới vào sau nút q (???)  Ngược lại thì báo lỗi 36
  • 37. Chương 3: Danh sách liên kết DSLK đơn  Các thao tác cơ bản  Tạo danh sách rỗng  Thêm một phần tử vào danh sách  Duyệt danh sách  Tìm kiếm một giá trị trên danh sách  Xóa một phần tử ra khỏi danh sách  Hủy toàn bộ danh sách  … 37
  • 38. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Duyệt danh sách  Là thao tác thường được thực hiện khi có nhu cầu muốn lấy lần lượt từng phần tử trong danh sách để xử lý, chẳng hạn xử lý:  Xuất các phần tử trong danh sách  Đếm các phần tử trong danh sách  Tính tổng các phần tử trong danh sách  Tìm tất cả các phần tử danh sách thoả điều kiện nào đó  Hủy toàn bộ danh sách (và giải phóng bộ nhớ)  … 38
  • 39. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Duyệt danh sách  Bước 1: p = pHead; //Cho p trỏ đến phần tử đầu danh sách  Bước 2: Trong khi (chưa hết danh sách) thực hiện:  B2.1 : Xử lý phần tử p  B2.2 : p=p->pNext; // Cho p trỏ tới phần tử kế 39 Node *p = l.pHead; while ( p!=NULL ) { // xử lý cụ thể p tùy ứng dụng p = p->pNext; } Chuyển thành vòng lặp for??
  • 40. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Ví dụ: In các phần tử trong danh sách 40 void Output (List l) { Node* p=l.pHead; while (p!=NULL) { cout<<p->data<<“t”; p=p->pNext; } cout<<endl; }
  • 41. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Đếm số nút trong danh sách: 41 int CountNodes (List l) { int count = 0; Node *p = l.pHead; while (p!=NULL) { count++; p = p->pNext; } return count; } Gọi hàm???
  • 42. Chương 3: Danh sách liên kết DSLK đơn  Các thao tác cơ bản  Tạo danh sách rỗng  Thêm một phần tử vào danh sách  Duyệt danh sách  Tìm kiếm một giá trị trên danh sách  Xóa một phần tử ra khỏi danh sách  Hủy toàn bộ danh sách  … 42
  • 43. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở 43  Tìm kiếm một phần tử có khóa x Node* Search (List l, int x) { Node* p = l.pHead; while ( p!=NULL ) { if ( p->data==x ) return p; p=p->pNext; } return NULL; } Gọi hàm???
  • 44. Chương 3: Danh sách liên kết DSLK đơn  Các thao tác cơ bản  Tạo danh sách rỗng  Thêm một phần tử vào danh sách  Duyệt danh sách  Tìm kiếm một giá trị trên danh sách  Xóa một phần tử ra khỏi danh sách  Hủy toàn bộ danh sách  … 44
  • 45. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Xóa một node của danh sách  Xóa node đầu danh sách  Xóa node sau node q trong danh sách  Xóa node có khoá k 45
  • 46. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Thuật toán: Xóa node đầu danh sách  Bước 1: Nếu danh sách rỗng thì không xóa được và thoát ct, ngược lại qua Bước 2  Bước 2: Gọi p là node đầu của danh sách (p=pHead)  Bước 3: Cho pHead trỏ vào node sau node p (pHead =p->pNext)  Bước 4: Nếu không còn node nào thì pTail = NULL  Bước 5: Giải phóng vùng nhớ mà p trỏ tới 46
  • 47. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Minh họa: Xóa node đầu danh sách 47 A B C D E pHead pTail p pHead = p->pNext; delete p;
  • 48. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở // xóa được: hàm trả về 1 // xóa không được: hàm trả về 0 int removeHead (List &l){ if (l.pHead == NULL) return 0; Node* p=l.pHead; l.pHead = p->pNext; if (l.pHead == NULL) l.pTail=NULL; //Nếu danh sách rỗng delete p; return 1; } 48 Cài đặt: Xóa node đầu danh sách
  • 49. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Xóa một node của danh sách  Xóa node đầu danh sách  Xóa node sau node q trong danh sách  Xóa node có khoá k 49
  • 50. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Thuật toán: Xóa node sau node q trong danh sách:  Điều kiện để có thể xóa được node sau q là:  q phải khác NULL (q !=NULL)  Node sau q phải khác NULL (q->pNext !=NULL)  Thuật toán:  Bước 1: Gọi p là node sau q  Bước 2: Cho q trỏ vào node đứng sau p  Bước 3: Nếu p là phần tử cuối thì pTail là q  Bước 4: Giải phóng vùng nhớ mà p trỏ tới 50
  • 51. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Minh họa: Xóa node sau node q trong danh sách 51 A B C D E pHead pTail q p q->pNext = p->pNext; delete p;
  • 52. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Cài đặt: Xóa node sau node q trong danh sách 52 // xóa được: hàm trả về 1 // xóa không được: hàm trả về 0 int removeAfter (List &l, Node* q ){ if (q !=NULL && q->pNext !=NULL) { Node* p = q->pNext; q->pNext = p->pNext; if (p==l.pTail) l.pTail = q; delete p; return 1; } else return 0; }
  • 53. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Xóa một node của danh sách  Xóa node đầu của danh sách  Xóa node sau node q trong danh sách  Xóa node có khoá k 53
  • 54. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở Thuật toán: Xóa 1 node có khoá k  Bước 1:  Tìm node có khóa k (gọi là p) và node đứng trước nó (gọi là q)  Bước 2:  Nếu (p!= NULL) thì // tìm thấy k  Hủy p ra khỏi danh sách: tương tự hủy phần tử sau q  Ngược lại  Báo không có k 54
  • 55. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Cài đặt: Xóa 1 node có khoá k 55 int removeNode (List &l, int k) { Node *p = l.pHead; Node *q = NULL; while (p != NULL) { if (p->data == k) break; q = p; p = p->pNext; } if (p == NULL) { cout<<“Không tìm thấy k”; return 0;} else if (q == NULL) // thực hiện xóa phần tử đầu ds là p else // thực hiện xóa phần tử p sau q } Tìm phần tử p có khóa k và phần tử q đứng trước nó A B C D E pHead pTail
  • 56. Chương 3: Danh sách liên kết DSLK đơn  Các thao tác cơ bản  Tạo danh sách rỗng  Thêm một phần tử vào danh sách  Duyệt danh sách  Tìm kiếm một giá trị trên danh sách  Xóa một phần tử ra khỏi danh sách  Hủy toàn bộ danh sách  … 56
  • 57. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Hủy toàn bộ danh sách  Để hủy toàn bộ danh sách, thao tác xử lý bao gồm hành động giải phóng một phần tử, do vậy phải cập nhật các liên kết liên quan:  Thuật toán:  Bước 1: Trong khi (chưa hết danh sách) thực hiện:  B1.1:  p = pHead;  pHead = pHead ->pNext; // Cho p trỏ tới phần tử kế  B1.2:  Hủy p;  Bước 2:  pTail = NULL; //Bảo đảm tính nhất quán khi xâu rỗng 57
  • 58. Chương 3: Danh sách liên kết DSLK đơn – Các thao tác cơ sở  Cài đặt: Hủy toàn bộ danh sách 58 void RemoveList (List &l) { Node *p; while (l.pHead!=NULL) { p = l.pHead; l.pHead = p->pNext; delete p; } l.pTail = NULL; } Gọi hàm???
  • 59. Chương 3: Danh sách liên kết Danh sách liên kết đơn (DSLK đơn)  Khai báo  Các thao tác cơ bản trên DSLK đơn  Sắp xếp trên DSLK đơn 59
  • 60. Chương 3: Danh sách liên kết Sắp xếp trên DSLK đơn  Các cách tiếp cận:  Phương án 1: Hoán vị nội dung các phần tử trong danh sách (thao tác trên vùng data)  Sử dụng thêm vùng nhớ trung gian  thích hợp cho DSLK với thành phần data có kích thước nhỏ  Phương án 2: Thay đổi các mối liên kết (thao tác trên vùng pNext)  Phức tạp hơn 60
  • 61. Chương 3: Danh sách liên kết Sắp xếp trên DSLK đơn: Hoán vị data  Cài đặt bằng pp đổi chỗ trực tiếp (Interchange Sort) void InterChangeSort (List &l) { for (Node* p=l.pHead; p!=l.pTail; p=p->pNext) for (Node* q=p->pNext; q!=NULL; q=q->pNext) if (p->data > q->data) Swap (p->data, q->data); } 61
  • 62. Chương 3: Danh sách liên kết Sắp xếp trên DSLK đơn: Hoán vị data 62 12 2 8 1 5 p q l.pHead l.pTail
  • 63. Chương 3: Danh sách liên kết Sắp xếp trên DSLK đơn: Hoán vị data 63 1 12 8 2 5 p q l.pHead l.pTail
  • 64. Chương 3: Danh sách liên kết 64 1 2 12 8 5 p q l.pHead l.pTail Sắp xếp trên DSLK đơn: Hoán vị data
  • 65. Chương 3: Danh sách liên kết 65 1 2 5 12 8 p q l.pHead l.pTail Sắp xếp trên DSLK đơn: Hoán vị data
  • 66. Chương 3: Danh sách liên kết 66 1 2 5 8 12 p q ng l.pHead l.pTail Sắp xếp trên DSLK đơn: Hoán vị data
  • 67. Chương 3: Danh sách liên kết Sắp xếp bằng pp chọn trực tiếp (Selection sort) void ListSelectionSort (List &l) { for ( Node* p = l.pHead ; p != l.pTail ; p = p->pNext ) { Node* min = p; for ( Node* q = p-> pNext; q != NULL ; q = q-> pNext ) if ( min->data > q->data ) min = q ; Swap(min->data, p->data); } } 67
  • 68. Chương 3: Danh sách liên kết Sắp xếp trên DSLK đơn: Thay đổi liên kết  Một trong những cách thay đổi liên kết đơn giản nhất là tạo một danh sách mới là danh sách có thứ tự từ danh sách cũ (GT.101)  Bước 1: Khởi tạo danh sách mới Result là rỗng;  Bước 2: Tìm phần tử nhỏ nhất min trong danh sách cũ l;  Bước 3: Tách min khỏi danh sách l;  Bước 4: Chèn min vào cuối danh sách Result;  Bước 5: Lặp lại bước 2 khi chưa hết danh sách cũ l; 68
  • 69. 69 void SortList( List &l ){ List lResult; Init( lResult ); Node *p,*q, *min, *minprev; while( l.pHead != NULL ){ min = l.pHead; q = min->pNext; p = l.pHead; minprev = NULL; while ( q != NULL ) { if (min->data >q->data ) { min = q; minprev = p; } p = q; q = q->pNext; } if ( minprev != NULL ) minprev->pNext = min->pNext; else l.pHead = min->pNext; min->pNext = NULL; addTail( lResult, min ); } l = lResult; } 5 4 3 9 minminprev