You are on page 1of 36

TRƯỜNG ĐH KHOA HỌC TỰ NHIÊN - ĐHQG TPHCM

KHOA TOÁN - TIN HỌC


BỘ MÔN ỨNG DỤNG TIN HỌC

Linked List
THỰC HÀNH CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT
TUẦN 10 - THÁNG 01 NĂM 2024

1
Tham khảo cách dùng con trỏ (Pointer)
trong C tại các slide:
In03 - Con trỏ
In05 - Hàm

2
Table of contents

01 02 03
Linked List Insertion Deletion
A brief introduction to a new Insert a node in a list Delete a node from a list
data structure

06 05 04
Dynamic Memory
Homework Practices
Allocation
Everything, everywhere all Insertion malloc()
at once Deletion
01
Linked List
Single linked list

4
DATA POINTER
Mỗi node trong một danh sách liên kết
đơn chứa 2 thành phần: dữ liệu và con trỏ
8 1x098e72
đến node tiếp theo.
Danh sách liên kết đơn có phần HEAD là
HEAD
nút đầu tiên trong danh sách, TAIL là nút
1x098e72
cuối cùng trong danh sách mà phần con
trỏ của nó mang giá trị NULL.
12 1x011f21
Danh sách liên kết đơn hỗ trợ rất tốt trong
việc cài đặt và quản lý Stack và Queue.
Ngoài ra, danh sách liên kết đơn còn có
thể được dùng để triển khai cây nhị phân 1x011f21
(binary tree), cây tìm kiếm nhị phân
(binary search tree) và đồ thị (graph). 19 NULL

TAIL
5
Để khai báo một node trong danh struct Node{
sách liên kết, ta sử dụng một cấu int data;
trúc struct gồm có 2 thành phần:
struct Node* next;
- Data kèm theo kiểu dữ liệu phù };
hợp (int, float, char,...)
- Con trỏ kiểu struct next và trỏ
đến thành phần data của nút typedef struct NodeType {
tiếp theo. int data;
struct NodeType* next;
Ngoài ra ta có thể định nghĩa thêm } Node;
cấu trúc danh sách liên kết để tiện
cho các thao tác trong tương lai. typedef struct LinkedListType {
Node* head;
Thư viện <stdlib.h> hỗ trợ rất tốt cho } LinkedList;
các khai báo trên.

6
02
Insertion
Insert a node in a list

7
Insert at Head
Để chèn một nút mới vào đầu của danh
sách liên kết, ta làm từng bước sau:
1x012e11
Bước 1: Khởi tạo một nút mang data
cần chèn và con trỏ mang giá trị NULL
bằng cách yêu cầu máy tính cấp phát 8 1x098e72
một vùng nhớ cho nút này.

HEAD

12 1x011f21
1x013e11

7 NULL
19 NULL

TAIL
8
1x013e11

Insert at Head 7 1x012e11


Để chèn một nút mới vào đầu của
danh sách liên kết, ta làm từng
bước sau: 1x012e11

Bước 1: Khởi tạo một nút mang data


cần chèn và con trỏ mang giá trị 8 1x098e72
NULL bằng cách yêu cầu máy tính
cấp phát một vùng nhớ cho nút
này. HEAD
Bước 2: Next của node mới trỏ đến
HEAD. 12 1x011f21

19 NULL

TAIL
9
1x013e11

Insert at Head 7 1x012e11


Để chèn một nút mới vào đầu của
danh sách liên kết, ta làm từng HEAD
bước sau: 1x012e11

Bước 1: Khởi tạo một nút mang data


cần chèn và con trỏ mang giá trị 8 1x098e72
NULL bằng cách yêu cầu máy tính
cấp phát một vùng nhớ cho nút
này.
Bước 2: Next của node mới trỏ đến
HEAD. 12 1x011f21

Bước 3: Node mới trở thành HEAD.

19 NULL

TAIL
10
Insert at Tail
1x012e11

8 1x098e72
Để chèn một nút mới vào cuối của danh
sách liên kết, ta làm từng bước sau:
Bước 1: Khởi tạo một nút mang data
HEAD
cần chèn và con trỏ mang giá trị NULL
bằng cách yêu cầu máy tính cấp phát 12 1x011f21
một vùng nhớ cho nút này.

19 NULL
1x013e11

TAIL
7 NULL

11
Insert at Tail
1x012e11

8 1x098e72
Để chèn một nút mới vào cuối của danh
sách liên kết, ta làm từng bước sau:
Bước 1: Khởi tạo một nút mang data HEAD
cần chèn và con trỏ mang giá trị NULL
bằng cách yêu cầu máy tính cấp phát 12 1x011f21
một vùng nhớ cho nút này.
Bước 2: Tìm đến node cuối cùng (Tail).
Next của Tail hiện tại trỏ đến node cần
chèn. 19 1x013e11
Bước 3: Tail là node mới.
1x013e11

7 NULL

TAIL
12
Insert at anywhere
Để chèn một nút vào giữa danh sách
8 1x098e72
liên kết, ta làm các bước như sau:
Bước 1: Khởi tạo một nút mang data
cần chèn và con trỏ mang giá trị NULL HEAD
bằng cách yêu cầu máy tính cấp phát 1x098e72
một vùng nhớ cho nút này.
12 1x011f21
1x013e11

7 NULL 1x011f21

19 NULL

TAIL
13
Insert at anywhere 8 1x098e72

Để chèn một nút vào giữa danh sách


HEAD
liên kết, ta làm các bước như sau: 1x098e72

Bước 1: Khởi tạo một nút mang data


cần chèn và con trỏ mang giá trị NULL 12
bằng cách yêu cầu máy tính cấp phát
một vùng nhớ cho nút này.
Bước 2: Tìm đến node mà ta cần chèn 1x013e11
vào sau nó và gán con trỏ next của nó
cho con trỏ next của node cần chèn.
7 1x011f21

1x011f21

19 NULL

TAIL
14
Insert at anywhere 8 1x098e72

Để chèn một nút vào giữa danh sách


HEAD
liên kết, ta làm các bước như sau: 1x098e72

Bước 1: Khởi tạo một nút mang data


cần chèn và con trỏ mang giá trị NULL 12 1x013e11
bằng cách yêu cầu máy tính cấp phát
một vùng nhớ cho nút này.
Bước 2: Tìm đến node mà ta cần chèn 1x013e11
vào sau nó và gán con trỏ next của nó
cho con trỏ next của node cần chèn.
7 1x011f21
Bước 3: Next của node cần chèn trỏ
đến node sau nó.
1x011f21

19 NULL

TAIL
15
03
Deletion
Delete a node from a list

16
Delete at head
Để xoá một nút ở đầu danh sách liên
8 1x098e72
kết, ta cần:
Bước 1: Gán HEAD cho node thứ hai
bằng cách gán head cho con trỏ next
của chính nó hiện tại (1x098e72). 1x098e72

12 1x011f21

HEAD
1x011f21

19 NULL

TAIL
17
Delete at head
Để xoá một nút ở đầu danh sách liên
8 1x098e72
kết, ta cần:
Bước 1: Gán HEAD cho node thứ hai
bằng cách gán head cho con trỏ next
của chính nó hiện tại (1x098e72). 1x098e72

Bước 2: Giải phóng vùng nhớ lưu trữ


node vừa xoá. 12 1x011f21

HEAD
1x011f21

19 NULL

TAIL
18
Delete at tail
Để xoá một nút ở cuối danh sách liên
8 1x098e72
kết, ta cần:
Bước 1: Duyệt đến node trước TAIL.
Gán con trỏ next của node đó cho HEAD
NULL. Gán TAIL cho node này. 1x098e72

12 NULL

TAIL
1x011f21

19 NULL

19
Delete at tail
Để xoá một nút ở cuối danh sách liên
8 1x098e72
kết, ta cần:
Bước 1: Duyệt đến node trước TAIL.
Gán con trỏ next của node đó cho HEAD
NULL. Gán TAIL cho node này. 1x098e72

Bước 2: Giải phóng vùng nhớ lưu trữ


node cần xoá. 12 NULL

TAIL
1x011f21

19 NULL

20
Delete at anywhere
Để xoá một nút ở giữa danh sách liên
8 1x098e72
kết, ta cần thực hiện các bước sau:

HEAD
1x098e72

12 1x011f21

1x011f21

19 NULL

TAIL
21
Delete at anywhere
Để xoá một nút ở giữa danh sách liên
8 1x011f21
kết, ta cần thực hiện các bước sau:
Bước 1: Duyệt đến node cần xoá và một
node trước nó. Gán con trỏ next của HEAD
node cần xoá cho con trỏ next của 1x098e72
node trước nó.
12 1x011f21

1x011f21

19 NULL

TAIL
22
Delete at anywhere
Để xoá một nút ở giữa danh sách liên
8 1x011f21
kết, ta cần thực hiện các bước sau:
Bước 1: Duyệt đến node cần xoá và một
node trước nó. Gán con trỏ next của HEAD
node cần xoá cho con trỏ next của 1x098e72
node trước nó.
Bước 2: Giải phóng vùng nhớ lưu trữ 12 1x011f21
node cần xoá.

1x011f21

19 NULL

TAIL
23
04
Dynamic
Memory Allocation
malloc()

24
Malloc là hàm được sử dụng để cấp phát bộ nhớ
động. Tên của hàm malloc viết tắt từ "memory

malloc(size)
allocation" (cấp phát bộ nhớ).
Hàm malloc nhận một tham số là size, đại diện cho số
byte mà bạn muốn cấp phát. Hàm này trả về một con
trỏ (kiểu void*) trỏ đến vùng nhớ mới được cấp phát.
Khi gọi hàm malloc, hệ điều hành sẽ tìm kiếm một
Kiểu: Hàm
vùng nhớ trống trong heap (một khu vực trong bộ
INPUT: kích cỡ byte
nhớ) có đủ kích thước để chứa số byte được yêu cầu.
OUTPUT: địa chỉ vùng nhớ
Nếu tìm thấy, hệ điều hành sẽ cấp phát vùng nhớ đó
được cấp phát hoặc NULL
và trả về con trỏ đến địa chỉ đầu của vùng nhớ. Ngược
nếu không tìm được.
lại, nếu không có đủ vùng nhớ trống, hàm malloc sẽ
Hàm đi kèm: free() dùng để
trả về con trỏ không hợp lệ (NULL).
giải phóng vùng nhớ được
cấp phát. Sau khi nhận được con trỏ từ hàm malloc, ta có thể sử
dụng vùng nhớ đó để lưu trữ dữ liệu theo ý muốn. Khi
không cần thì phải giải phóng vùng nhớ đã cấp phát
bằng cách sử dụng hàm free().

25
05

Practice
Insertion - Deletion

26
Practice 01 #include <stdio.h> //Hàm in linked list
#include <stdlib.h> void printList(LinkedList*
list){
//Định nghĩa node Node* node = list->head;
Cho cấu trúc node và các hàm với typedef struct NodeType { while (node != NULL) {

chức năng như đoạn code bên. int data; printf("Node address:
struct NodeType* next; %p | ", &(node->data));
}Node; printf("data = %d| ",
1. Hãy bổ sung các đoạn code còn //Định nghĩa Linked list
node->data);
printf("next node
thiếu để hoàn thiện chương trình typedef struct address = %p\n ",
LinkedListType{ node->next);
với chức năng tạo một danh sách Node* head; node = node->next;

liên kết đơn lưu các số từ 0 đến


}LinkedList; }
printf("\n");
9 và in danh sách đó. //Khởi tạo linked list
void init(LinkedList* list) {
}

2. Hãy thêm số 15 vào đầu danh }


list->head = NULL; //Hàm main
int main(){
sách trên. LinkedList list;
init(&list);
//Hàm tạo node mới
3. Viết hàm xoá phần tử đầu ra Node* makeNode(int data){} //Tạo danh sách tự động
for(int i = 0; i < 10;
khỏi danh sách liên kết: //Hàm chèn node mới vào đầu i++)
danh sách insertHead(i, &list);
void deleteHead(LinkedList* list){} void insertHead(int data, //In danh sách
LinkedList* list){} printList(&list);
return 0;
}
27
Practice 02
Cho danh sách liên kết đơn đang có sẵn các nút mang giá trị:

2 12 9 0 11 3 4 8
1. Tạo danh sách liên kết trên với phần tử HEAD là 2.
2. Hãy chèn:
a. Số 19 vào đầu danh sách (19 2 12 9 0 11 3 4 8)
b. Số -3 vào cuối của danh sách (19 2 12 9 0 11 3 4 -3)
3. Hãy xoá:
a. Số 19 khỏi danh sách liên kết.
b. Số -3 khỏi danh sách liên kết.

28
06
Homeworks
Everything, everywhere all at once

29
Homework 01
1.1 Viết hàm chèn một node vào vị trí thứ k trong một danh
sách liên kết đơn.
Ví dụ: 2 3 4 5 6 7, data cần chèn là 1 và vị trí cần chèn là k = 2 thì ta được
danh sách mới là 2 1 3 4 5 6 7

1.2 Viết hàm xoá một node tại vị trí thứ k trong một danh
sách liên kết đơn.
Ví dụ: 2 3 4 5 6 7, vị trí cần xoá là k = 2 thì ta được danh sách mới là 2 4 5 6 7

30
Homework 02
Cho cấu trúc dữ liệu danh sách liên kết sau với typedef struct NodeType {
Node là cấu trúc của một node trong danh sách, int data;
và LinkedList là cấu trúc của một danh sách liên struct NodeType* next;
} Node;
kết.
typedef struct LinkedListType {
a. Hãy cài đặt hàm Node* head;
void insert(LinkedList* list, int data); } LinkedList;
để chèn dữ liệu data vào một node mới của
danh sách liên kết list, sao cho danh sách có
thứ tự giảm dần.
b. Hãy cài đặt hàm
void delete(LinkedList* list, int value);
để xóa một node nếu có dữ liệu là value của
danh sách liên kết list, có thứ tự tăng dần.

31
Homework 03

3.1 Dùng danh sách liên kết đơn thay cho mảng để cài đặt
một ngăn xếp (Stacks) với các phần tử là số nguyên.
3.2 Dùng danh sách liên kết đơn thay cho mảng để cài đặt
một hàng đợi (Queue) với các phần tử là số nguyên.
Các cài đặt stacks và queue đều bao gồm các phép toán đi
kèm ứng với mỗi câu 3.1 và 3.2.

32
Homework 04

Nếu homework 01 không dùng đệ quy thì cài đặt lại 1.1 và
1.2 sử dụng kỹ thuật đệ quy.
Ta có thể đánh giá được các hàm đệ quy trên theo quy trình
4 bước không?
- Nếu có thì hãy trình bày câu trả lời.
- Nếu không thì hãy giải thích vì sao.

33
Homework 05
Một khách sạn có 17 tầng, mỗi tầng có 12 phòng được gán mã theo cú pháp

P[số tầng].[số phòng]

Ví dụ: Tầng 3, phòng 3 thì có mã là P3.3.

Mô tả: Có n đoàn khách, mỗi đoàn gồm m người đến check-in nhận phòng. Vì có những
khách lẻ đã đặt phòng trước đó nên không thể xếp cho cả 1 đoàn khách ở cùng một
tầng, do đó các khách trong đoàn được xếp ngẫu nhiên vào các phòng trống rời rạc sao
cho khi truy cập thông tin vào một phòng, ta có thể biết tên (chữ cái đầu) của khách và
địa chỉ phòng của người tiếp theo trong đoàn khách. Biết rằng phòng của các trưởng
đoàn luôn ở tầng trệt (tầng 0). Giả sử sức chứa của mỗi phòng là 01 người.

Vấn đề 1: Cho trước trạng thái các phòng hiện tại của khách sạn với ký hiệu “0” tương
ứng với “còn trống” và “1” tương ứng với “đã có người”. Hãy xếp n đoàn khách vào các
phòng sao cho không còn phòng nào “còn trống”.

34
Homework 05
Vấn đề 2: Nhân viên tiếp tân muốn xác nhận thông tin của một đoàn ngẫu nhiên thì chỉ
cần biết được vị trí phòng của trưởng đoàn. Hãy viết một hàm cho phép tiếp tân nhập
vào địa chỉ của trưởng đoàn của một đoàn khách bất kỳ, hàm sẽ trả về tất cả thông tin
của một đoàn bao gồm tên và vị trí phòng tương ứng của từng khách chung đoàn.

Vấn đề 3: Biết rằng lúc này có một số khách lẻ check-out nên xuất hiện một số phòng
trống. Đột nhiên một số đoàn khách báo cáo với khách sạn về việc bổ sung một số khách
mới cần check-in. Hãy bổ sung các vị khách này vào các đoàn tương ứng.

Vấn đề 4: Một số khách của một số đoàn có công việc bận đột xuất nên check-out ngay
trong đêm và tiếp tân muốn kiểm tra lại thông tin của các đoàn như ở Vấn đề 2. Hãy
chỉnh sửa thông tin của các đoàn để chuẩn bị cho cuộc kiểm tra của tiếp tân.

Vấn đề 5: Một đoàn khách (đã check-in trước đó) muốn check-out cho cả đoàn. Hãy thực
hiện chỉnh sửa trạng thái của các phòng mà khách đã check-out theo thứ tự và báo cáo
trạng thái các phòng của khách sạn lúc này.
35
Homework 05 1 1 1

Ví dụ
1 1 1 1 1 1

1 1 1 1 1

Cho khách sạn đang có trạng thái như hình bên.


1 1 1 1 1 1

120 ô không có số được xem như “đang trống”. 1 1 1 1

Cho danh sách các đoàn như sau với tên người 1 1 1 1 1 1 1 1

đầu tiên là đoàn trưởng. 1 1 1 1 1

Đoàn 1: (12) A B S E F J K L S W Q A 1 1 1 1 1

Đoàn 2: (10) T M K L J S A Q C S 1 1 1 1 1

Đoàn 3: (9) H J S S A S M Q D
Đoàn 4: (13) S A Q D A S S A Q D S Q A 1 1 1 1 1

Đoàn 5: (15) Q S A Q E D F S S A S X V B F 1 1 1 1

Đoàn 6: (14) H A V A N T H A O T T H U S
Đoàn 7: (12) P H L A M D S A T T H U
1 1 1 1 1 1

Đoàn 8: (15) P P N H U N G S V E L E V E N 1 1 1 1 1

Đoàn 9: (10) L P T R U O N G D S 1 1 1 1
Đoàn 10: (10) C H G I A O K D L H
1 1 1 1 1 1

Các thông tin còn lại SV mô phỏng cho bài làm


1 1 1 1 1

của mình theo yêu cầu. 1 1

36

You might also like