Chương 3: Danh sách liên kết + DSLK Đơn - Cô Võ Thị Hường
Gửi bởi: Võ Thị Hường 10 tháng 9 2020 lúc 9:54:35 | Được cập nhật: hôm kia lúc 17:44:40 Kiểu file: PDF | Lượt xem: 485 | Lượt Download: 4 | File size: 1.709257 Mb
Nội dung tài liệu
Tải xuống
Link tài liệu:
Các tài liệu liên quan
Có thể bạn quan tâm
Thông tin tài liệu
CHAPTER 3: DANH SÁCH LIÊN KẾT
(LINKED LISTS)
GIÁO VIÊN: VÕ THỊ HƯỜNG
Nội dung
2
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)
Chương 6: Danh sách liên kết
Giới thiệu
3
Kiểu dữ liệu tĩnh
Khái niệm: Một số đối tượng dữ liệu không thay thay đổi được
kích thước, cấu trúc, … trong suốt quá trình sống. Các đối tượng
dữ liệu thuộc những kiểu dữ liệu gọi là 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 thực, kiểu 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 ...
Các đối tượng dữ liệu được xác định thuộc những kiểu dữ
liệu này thường cứng ngắt, gò bó khó diễn tả được thực tế
vốn sinh động, phong phú.
Chương 6: Danh sách liên kết
Giới thiệu
4
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, 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ả
Chương 6: Danh sách liên kết
Giới thiệu
5
Cấu trúc dữ liệu tĩnh: Ví dụ: Mảng 1 chiều
Kích thước cố định (fixed size)
Chèn 1 phần tử vào mảng rất khó
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
0
Chương 6: Danh sách liên kết
1
2
3
4
n-2
n-1
Giới thiệu
6
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
Thao tác thêm xoá đơn giản
Insert,
Delete
Chương 6: Danh sách liên kết
Giới thiệu
7
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
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
…
Chương 6: Danh sách liên kết
8
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
Chương 6: Danh sách liên kết
Giới thiệu
9
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:
A
B
X
Z
Y
Danh sách liên kết đôi: 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:
A
Chương 6: Danh sách liên kết
B
C
D
Giới thiệu
10
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
A
Chương 6: Danh sách liên kết
X
B
Z
C
Y
D
Nội dung
21
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)
Chương 6: Danh sách liên kết
Danh sách liên kết đơn (DSLK đơn)
22
Khai báo
Các thao tác cơ bản trên DSLK đơn
Sắp xếp trên DSLK đơn
Chương 6: Danh sách liên kết
DSLK đơn – Khai báo
23
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
Link
Khai báo node
Data
struct Node
{
DataType data; // DataType là kiểu đã định nghĩa trước
Node *pNext; // con trỏ chỉ đến cấu trúc Node
};
Chương 6: Danh sách liên kết
DSLK đơn – Khai báo
24
Ví dụ 1: Khai báo node lưu số
nguyên:
struct Node
{
int data;
Node *pNext;
};
Chương 6: Danh sách liên kết
Ví dụ 2: Định nghĩa một phần
tử trong danh sách đơn lưu
trữ hồ sơ sinh viên:
struct SinhVien {
char Ten[30];
int MaSV;
};
struct SVNode {
SinhVien data;
SVNode *pNext;
};
DSLK đơn – Khai báo
25
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;
pTail
pHead
A
Chương 6: Danh sách liên kết
B
X
Z
Y
DSLK đơn – Khai báo
26
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;
};
Chương 6: Danh sách liên kết
Khai báo biến kiểu danh sách:
List tên_biến;
DSLK đơn – Khai báo
27
Tạo một node mới
Thủ tục GetNode để tạo ra một nút cho danh sách với thông
tin chứa trong x
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;
Gọi
hàm??
}
Chương 6: Danh sách liên kết
Danh sách liên kết đơn (DSLK đơn)
29
Khai báo
Các thao tác cơ bản trên DSLK đơn
Sắp xếp trên DSLK đơn
Chương 6: Danh sách liên kết
DSLK đơn
30
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
…
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
31
Tạo danh sách rỗng
pTail
pHead
void Init(List &l)
{
l.pHead = l.pTail = NULL;
}
Chương 6: Danh sách liên kết
DSLK đơn
32
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
…
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
33
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
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
34
Thêm một phần tử
Nếu danh sách ban đầu rỗng
pTail
pHead
pHead = pTail = new_node;
X
new_node
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
35
Thêm một phần tử
Nếu danh sách ban đầu không rỗng:
Gắn node vào đầu danh sách
pTail
pHead
A
X
new_node
Chương 6: Danh sách liên kết
B
C
D
E
new_node->pNext = pHead;
pHead = new_node;
DSLK đơn – Các thao tác cơ sở
36
Thuật toán: Gắn nút vào đầu DS
// input: danh sách, phần tử mới new_node
// output: danh sách với new_node ở đầu DS
Nếu DS rỗng thì
pHead = pTail = new_node;
Ngược lại
new_node->pNext = pHead;
pHead = new_node;
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
37
Cài đặt: Gắn nút vào đầu DS
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 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
38
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 (???)
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
39
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);
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
40
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
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
41
Thêm một phần tử
Nếu danh sách ban đầu rỗng
pTail
pHead
pHead = pTail = new_node;
X
new_node
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
42
Thêm một phần tử
Nếu danh sách ban đầu không rỗng:
pTail
Gắn node vào cuối danh sách:
pHead
A
B
pTail->pNext = new_node;
pTail = new_node;
Chương 6: Danh sách liên kết
C
D
E
X
new_node
DSLK đơn – Các thao tác cơ sở
43
Thuật toán: Thêm một phần tử vào cuối DS
// input: danh sách, phần tử mới new_node
// output: danh sách với new_node ở cuối DS
Nếu DS rỗng thì
pHead = pTail = new_node;
Ngược lại
pTail->pNext = new_node ;
pTail = new_node;
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
44
Cài đặt: Gắn nút vào cuối DS
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 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
45
Thuật toán: Thêm một thành phần dữ liệu vào cuối ds
// 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 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 cuối danh sách (???)
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
46
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);
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
47
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
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
48
Thêm một phần tử
Nếu danh sách ban đầu rỗng
pTail
pHead
pHead = pTail = new_node;
X
new_node
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
49
Thêm một phần tử
Nếu danh sách ban đầu rỗng
Chèn một phần tử sau q
q
pHead
A
pTail
B
C
X
new_node
Chương 6: Danh sách liên kết
D
E
DSLK đơn – Các thao tác cơ sở
50
Thuật toán: Chèn một phần tử sau q
// input: danh sách l, q, phần tử mới new_node
// output: danh sách với new_node ở sau q
Nếu (q != NULL) thì:
new_node -> pNext = q -> pNext;
q -> pNext = new_node ;
Nếu ( q == l.pTail) thì
l.pTail = new_node;
Ngược lại
Thêm new_node vào đầu danh sách
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
51
Cài đặt: Chèn một phần tử sau q
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 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
52
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
Chương 6: Danh sách liên kết
DSLK đơn
53
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
…
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
54
Duyệt danh sách
Là thao tác thường được thực hiện khi có nhu cầu xử lý các
phần tử của danh sách theo cùng một cách thức hoặc khi cần
lấy thông tin tổng hợp từ các phần tử của danh sách như:
Đếm các phần tử của danh sách
Tìm tất cả các phần tử thoả điều kiện
Hủy toàn bộ danh sách (và giải phóng bộ nhớ)
…
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
55
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 (Danh sách chưa hết) 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ế
void processList (List l)
{
Node *p = l.pHead;
while (p!= NULL)
{
// xử lý cụ thể p tùy ứng dụng
p = p->pNext;
}
}
Chương 6: Danh sách liên kết
DSLK đơn – Các thao tác cơ sở
56
Ví dụ: In các phần tử trong danh sách
void Output (List l)
{
Node* p=l.pHead;
while (p!=NULL)
{
cout<data<<“\t”;
p=p ->pNext;
}
cout<data==x)
return p;
p=p->pNext;
}
return NULL;
}
Chương 6: Danh sách liên kết
Gọi hàm???
DSLK đơn
61
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
…
Chương 6: Danh sách liên kết