CHAPTER 6: LINKED
LISTS
Cấu trúc dữ liệu động
3
Mục
Mục tiêu
tiêu
 Giới
Giới thiệu
thiệu khái
khái niệm
niệm cấu
cấu trúc
trúc dữ
dữ liệu
liệu động
động.
.
 Giới
Giới thiệu
thiệu danh
danh sách
sách liên
liên kết
kết:
:
 Các
Các kiểu
kiểu tổ
tổ chức
chức dữ
dữ liệu
liệu theo
theo DSLK
DSLK.
.
 Danh
Danh sách
sách liên
liên kết
kết đơn
đơn:
: tổ
tổ chức
chức,
, các
các thuật
thuật toán
toán,
, ứng
ứng
dụng
dụng.
.
4
Kiểu
Kiểu dữ
dữ liệu
liệu tĩnh
tĩnh
 Khái niệm : Một số đối tượng dữ liệu không thay thay đổi
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 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
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.
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
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
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
ký tự ... hoặc từ các cấu trúc đơn giản như mẩu tin, tập
hợp, mảng ...
hợp, mảng ...

 Các đối tượng dữ liệu được xác định thuộc những kiểu dữ
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ó
liệu này thường cứng ngắt, gò bó 
 khó diễn tả được thực
khó diễn tả được thực
tế vốn sinh động, phong phú.
tế vốn sinh động, phong phú.
5
CTDL
CTDL tĩnh
tĩnh –
– Một
Một số
số hạn
hạn chế
chế
 Một
Một số
số đối
đối tượng
tượng dữ
dữ liệu
liệu trong
trong chu
chu kỳ
kỳ sống
sống của
của nó
nó có
có thể
thể
thay
thay đổi
đổi về
về cấu
cấu trúc
trúc,
, độ
độ lớn
lớn,
, như
như danh
danh sách
sách các
các học
học viên
viên
trong
trong một
một lớp
lớp học
học có
có thể
thể tăng
tăng thêm
thêm,
, giảm
giảm đi
đi ...
... Nếu
Nếu dùng
dùng
những
những cấu
cấu trúc
trúc dữ
dữ liệu
liệu tĩnh
tĩnh đã
đã biết
biết như
như mảng
mảng để
để biểu
biểu diễn
diễn

 Những
Những thao
thao tác
tác phức
phức tạp
tạp,
, kém
kém tự
tự nhiên
nhiên 
 chương
chương trình
trình
khó
khó đọc
đọc,
, khó
khó bảo
bảo trì
trì và
và nhất
nhất là
là khó
khó có
có thể
thể sử
sử dụng
dụng bộ
bộ nhớ
nhớ
một
một cách
cách có
có hiệu
hiệu quả
quả.
.
 Dữ
Dữ liệu
liệu tĩnh
tĩnh sẽ
sẽ chiếm
chiếm vùng
vùng nhớ
nhớ đã
đã dành
dành cho
cho chúng
chúng suốt
suốt
quá
quá trình
trình hoạt
hoạt động
động của
của chương
chương trình
trình 
 sử
sử dụng
dụng bộ
bộ nhớ
nhớ
kém
kém hiệu
hiệu quả
quả.
.
6
CTDL tĩnh
CTDL tĩnh
 Mảng 1 chiều
Mảng 1 chiều
 Kích thước cố định (fixed size)
Kích thước cố định (fixed size)
 Chèn 1 phần tử vào mảng rất khó
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
Các phần tử tuần tự theo chỉ số 0 
 n-1
n-1
 Truy cập ngẫu nhiên (random access)
Truy cập ngẫu nhiên (random access)
0 1 2 3 4 n-2 n-1
chèn
7
Cấu trúc dữ liệu động
Cấu trúc dữ liệu động
 Danh sách liên kết
Danh sách liên kết
 Cấp phát động lúc chạy chương trình
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ớ
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
Kích thước danh sách chỉ bị giới hạn do RAM
 Thao tác thêm xoá đơn giản
Thao tác thêm xoá đơn giản
Insert,
Delete
8
Hướng
Hướng giải
giải quyết
quyết
 Cần
Cần xây
xây dựng
dựng cấu
cấu trúc
trúc dữ
dữ liệu
liệu đáp
đáp ứng
ứng được
được các
các yêu
yêu cầu
cầu:
:
 Linh
Linh động
động hơn
hơn.
.
 Có
Có thể
thể thay
thay đổi
đổi kích
kích thước
thước,
, cấu
cấu trúc
trúc trong
trong suốt
suốt thời
thời
gian
gian sống
sống.
.

 Cấu
Cấu trúc
trúc dữ
dữ liệu
liệu động
động.
.
Danh sách liên kết
Danh sách liên kết
( LINKED LIST )
( LINKED LIST )
10
Biến
Biến không
không động
động
Biến
Biến không
không động
động (
(biến
biến tĩnh
tĩnh,
, biến
biến nửa
nửa tĩnh
tĩnh)
) là
là những
những biến
biến thỏa
thỏa:
:
 Được
Được khai
khai báo
báo tường
tường minh
minh,
,
 Tồn
Tồn tại
tại khi
khi vào
vào phạm
phạm vi
vi khai
khai báo
báo và
và chỉ
chỉ mất
mất khi
khi ra
ra khỏi
khỏi phạm
phạm
vi
vi này
này,
,
 Được
Được cấp
cấp phát
phát vùng
vùng nhớ
nhớ trong
trong vùng
vùng dữ
dữ liệu
liệu (
(Data
Data segment
segment)
)
hoặc
hoặc là
là Stack
Stack (
(đối
đối với
với biến
biến nửa
nửa tĩnh
tĩnh -
- các
các biến
biến cục
cục bộ
bộ).
).
 Kích
Kích thước
thước không
không thay
thay đổi
đổi trong
trong suốt
suốt quá
quá trình
trình sống
sống.
.
 Do
Do được
được khai
khai báo
báo tường
tường minh
minh,
, các
các biến
biến không
không động
động có
có một
một
định
định danh
danh đã
đã được
được kết
kết nối
nối với
với địa
địa chỉ
chỉ vùng
vùng nhớ
nhớ lưu
lưu trữ
trữ biến
biến và
và
được
được truy
truy xuất
xuất trực
trực tiếp
tiếp thông
thông qua
qua định
định danh
danh đó
đó.
.
 Ví
Ví dụ
dụ :
:
int a; // a, b là các biến không động
char b[10];
11
Biến
Biến động
động
 Trong
Trong nhiều
nhiều trường
trường hợp
hợp,
, tại
tại thời
thời điểm
điểm biên
biên dịch
dịch không
không thể
thể
xác
xác định
định trước
trước kích
kích thước
thước chính
chính xác
xác của
của một
một số
số đối
đối tượng
tượng
dữ
dữ liệu
liệu do
do sự
sự tồn
tồn tại
tại và
và tăng
tăng trưởng
trưởng của
của chúng
chúng phụ
phụ thuộc
thuộc
vào
vào ngữ
ngữ cảnh
cảnh của
của việc
việc thực
thực hiện
hiện chương
chương trình
trình.
.
 Các
Các đối
đối tượng
tượng dữ
dữ liệu
liệu có
có đặc
đặc điểm
điểm kể
kể trên
trên nên
nên được
được khai
khai
báo
báo như
như biến
biến động
động.
. Biến
Biến động
động là
là những
những biến
biến thỏa
thỏa:
:
 Biến
Biến không
không được
được khai
khai báo
báo tường
tường minh
minh.
.
 Có
Có thể
thể được
được cấp
cấp phát
phát hoặc
hoặc giải
giải phóng
phóng bộ
bộ nhớ
nhớ khi
khi người
người
sử
sử dụng
dụng yêu
yêu cầu
cầu.
.
 Các
Các biến
biến này
này không
không theo
theo qui
qui tắc
tắc phạm
phạm vi
vi (
(tĩnh
tĩnh).
).
 Vùng
Vùng nhớ
nhớ của
của biến
biến được
được cấp
cấp phát
phát trong
trong Heap
Heap.
.
 Kích
Kích thước
thước có
có thể
thể thay
thay đổi
đổi trong
trong quá
quá trình
trình sống
sống.
.
12
Biến
Biến động
động
 Do
Do không
không được
được khai
khai báo
báo tường
tường minh
minh nên
nên các
các biến
biến động
động
không
không có
có một
một định
định danh
danh được
được kết
kết buộc
buộc với
với địa
địa chỉ
chỉ vùng
vùng
nhớ
nhớ cấp
cấp phát
phát cho
cho nó
nó,
, do
do đó
đó gặp
gặp khó
khó khăn
khăn khi
khi truy
truy xuất
xuất đến
đến
một
một biến
biến động
động.
.
 Để
Để giải
giải quyết
quyết vấn
vấn đề
đề,
, biến
biến con
con trỏ
trỏ (
(là
là biến
biến không
không động
động)
)
được
được sử
sử dụng
dụng để
để trỏ
trỏ đến
đến biến
biến động
động.
.
 Khi
Khi tạo
tạo ra
ra một
một biến
biến động
động,
, phải
phải dùng
dùng một
một con
con trỏ
trỏ để
để lưu
lưu địa
địa
chỉ
chỉ của
của biến
biến này
này và
và sau
sau đó
đó,
, truy
truy xuất
xuất đến
đến biến
biến động
động thông
thông
qua
qua biến
biến con
con trỏ
trỏ đã
đã biết
biết định
định danh
danh.
.
13
Biến
Biến động
động
 Hai
Hai thao
thao tác
tác cơ
cơ bản
bản trên
trên biến
biến động
động là
là tạo
tạo và
và hủy
hủy một
một biến
biến
động
động do
do biến
biến con
con trỏ
trỏ ‘p’
‘p’ trỏ
trỏ đến
đến:
:
 Tạo
Tạo ra
ra một
một biến
biến động
động và
và cho
cho con
con trỏ
trỏ ‘p’
‘p’ chỉ
chỉ đến
đến nó
nó
 Hủy
Hủy một
một biến
biến động
động do
do p
p chỉ
chỉ đến
đến
14
Biến
Biến động
động
 Tạo
Tạo ra
ra một
một biến
biến động
động và
và cho
cho con
con trỏ
trỏ ‘p’
‘p’ chỉ
chỉ đến
đến nó
nó
void* malloc(size); //
// trả
trả về
về con
con trỏ
trỏ chỉ
chỉ đến
đến vùng
vùng nhớ
nhớ
//
// size
size byte
byte vừa
vừa được
được cấp
cấp phát
phát.
.
void* calloc(n,size);//
// trả
trả về
về con
con trỏ
trỏ chỉ
chỉ đến
đến vùng
vùng nhớ
nhớ
//
// vừa
vừa được
được cấp
cấp phát
phát gồm
gồm n
n phần
phần tử
tử,
,
//
// mỗi
mỗi phần
phần tử
tử có
có kích
kích thước
thước size
size byte
byte
new //
// toán
toán tử
tử cấp
cấp phát
phát bộ
bộ nhớ
nhớ trong
trong C
C++
++
 Hàm
Hàm free
free(
(p
p)
) huỷ
huỷ vùng
vùng nhớ
nhớ cấp
cấp phát
phát bởi
bởi hàm
hàm malloc
malloc hoặc
hoặc
calloc
calloc do
do p
p trỏ
trỏ tới
tới
 Toán
Toán tử
tử delete p
p huỷ
huỷ vùng
vùng nhớ
nhớ cấp
cấp phát
phát bởi
bởi toán
toán tử
tử new do
do
p
p trỏ
trỏ tới
tới
15
Biến
Biến động
động –
– Ví
Ví dụ
dụ
int *p1, *p2;
// cấp phát vùng nhớ cho 1 biến động kiểu int
p1 = (int*)malloc(sizeof(int));
*p1 = 5; // đặt giá trị 5 cho biến động đang được p1
quản lý
// cấp phát biến động kiểu mảng gồm 10 phần tử kiểu int
p2 = (int*)calloc(10, sizeof(int));
*(p2+3) = 0; // đặt giá trị 0 cho phần tử thứ 4 của mảng
p2
free(p1);
free(p2);
16
Kiểu
Kiểu dữ
dữ liệu
liệu Con
Con trỏ
trỏ
 Kiểu
Kiểu con
con trỏ
trỏ là
là kiểu
kiểu cơ
cơ sở
sở dùng
dùng lưu
lưu địa
địa chỉ
chỉ của
của một
một đối
đối
tượng
tượng dữ
dữ liệu
liệu khác
khác.
.
 Biến
Biến thuộc
thuộc kiểu
kiểu con
con trỏ
trỏ Tp
Tp là
là biến
biến mà
mà giá
giá trị
trị của
của nó
nó là
là địa
địa
chỉ
chỉ cuả
cuả một
một vùng
vùng nhớ
nhớ ứng
ứng với
với một
một biến
biến kiểu
kiểu T
T,
, hoặc
hoặc là
là
giá
giá trị
trị NULL
NULL.
.
17
Con
Con trỏ
trỏ –
– Khai
Khai báo
báo
 Cú
Cú pháp
pháp định
định nghĩa
nghĩa một
một kiểu
kiểu con
con trỏ
trỏ trong
trong ngôn
ngôn ngữ
ngữ C
C :
:
typedef <kiểu cơ sở> * < kiểu con trỏ>;
 Ví
Ví dụ
dụ :
:
typedef int *intpointer;
intpointer p;
hoặc
hoặc
int *p;
là
là những
những khai
khai báo
báo hợp
hợp lệ
lệ.
.
18
Con
Con trỏ
trỏ –
– Thao
Thao tác
tác căn
căn bản
bản
 Các
Các thao
thao tác
tác cơ
cơ bản
bản trên
trên kiểu
kiểu con
con trỏ
trỏ:(
:(minh
minh họa
họa bằng
bằng C
C)
)
 Khi
Khi 1
1 biến
biến con
con trỏ
trỏ p
p lưu
lưu địa
địa chỉ
chỉ của
của đối
đối tượng
tượng x
x,
, ta
ta nói
nói
‘p
‘p trỏ
trỏ đến
đến x’
x’.
.
 Gán
Gán địa
địa chỉ
chỉ của
của một
một vùng
vùng nhớ
nhớ con
con trỏ
trỏ p
p:
:
p
p = <
= <địa
địa chỉ
chỉ>;
>;
ví duï :
ví duï :
int i,*
int i,*p;
p;
p=&i;
p=&i;
 Truy
Truy xuất
xuất nội
nội dung
dung của
của đối
đối tượng
tượng do
do p
p trỏ
trỏ đến
đến (*
(*p
p)
)
19
Danh
Danh sách
sách liên
liên kết
kết (
(List
List)
)
I.
I. Định
Định nghĩa
nghĩa:
:
Moät danh saùch (list) laø moät taäp hôïp
Moät danh saùch (list) laø moät taäp hôïp
goàm moät soá höõu haïn phaàn töû
goàm moät soá höõu haïn phaàn töû
cuøng kieåu, coù thöù töï.
cuøng kieåu, coù thöù töï.
Coù hai caùch caøi ñaët danh saùch laø :
Coù hai caùch caøi ñaët danh saùch laø :
 Caøi ñaët theo kieåu keá tieáp : ta coù
Caøi ñaët theo kieåu keá tieáp : ta coù
danh saùch keà hay danh saùch ñaëc.
danh saùch keà hay danh saùch ñaëc.
 Caøi ñaët theo kieåu lieân keát : ta coù
Caøi ñaët theo kieåu lieân keát : ta coù
danh saùch lieân keát.
danh saùch lieân keát.
20
Danh
Danh sách
sách liên
liên kết
kết (
(List
List)
)
a.
a. Danh saùch keà :
Danh saùch keà :
 Caùc phaàn töû cuûa danh saùch goïi laø caùc node,
Caùc phaàn töû cuûa danh saùch goïi laø caùc node,
ñöôïc löu tröõ keà lieàn nhau trong boä nhôù. Moãi
ñöôïc löu tröõ keà lieàn nhau trong boä nhôù. Moãi
node coù theå laø moät giaù trò kieåu int, float, char, …
node coù theå laø moät giaù trò kieåu int, float, char, …
hoaëc coù theå laø moät struct vôùi nhieàu vuøng tin.
hoaëc coù theå laø moät struct vôùi nhieàu vuøng tin.
Maûng hay chuoãi laø daïng cuûa danh saùch keà.
Maûng hay chuoãi laø daïng cuûa danh saùch keà.
 Ñòa chæ cuûa moãi node trong danh saùch ñöôïc xaùc
Ñòa chæ cuûa moãi node trong danh saùch ñöôïc xaùc
ñònh baèng chæ soá (index). Chæ soá cuûa danh saùch
ñònh baèng chæ soá (index). Chæ soá cuûa danh saùch
laø moät soá nguyeân vaø ñöôïc ñaùnh töø 0 ñeán moät
laø moät soá nguyeân vaø ñöôïc ñaùnh töø 0 ñeán moät
giaù trò toái ña naøo ñoù.
giaù trò toái ña naøo ñoù.
 Danh saùch keà laø caáu truùc döõ lieäu tónh, soá node
Danh saùch keà laø caáu truùc döõ lieäu tónh, soá node
toái ña cuûa danh saùch keà coá ñònh sau khi caáp
toái ña cuûa danh saùch keà coá ñònh sau khi caáp
phaùt neân soá node caàn duøng coù khi thöøa hay
phaùt neân soá node caàn duøng coù khi thöøa hay
thieáu. Ngoaøi ra danh saùch keà khoâng phuø hôïp
thieáu. Ngoaøi ra danh saùch keà khoâng phuø hôïp
vôùi caùc thao taùc thöôøng xuyeân nhö theâm hay
vôùi caùc thao taùc thöôøng xuyeân nhö theâm hay
xoùa phaàn töû treân danh saùch,
xoùa phaàn töû treân danh saùch,
21
Danh
Danh sách
sách liên
liên kết
kết (
(List
List)
)
b.
b. Danh saùch lieân keát :
Danh saùch lieân keát :
 Caùc phaàn töû cuûa danh saùch goïi laø node, naèm
Caùc phaàn töû cuûa danh saùch goïi laø node, naèm
raûi raùc trong boä nhôù. Moãi node, ngoaøi vuøng
raûi raùc trong boä nhôù. Moãi node, ngoaøi vuøng
döõ lieäu thoâng thöôøng, coøn coù vuøng lieân keát
döõ lieäu thoâng thöôøng, coøn coù vuøng lieân keát
chöùa ñòc chæ cuûa node keá tieáp hay node tröôùc
chöùa ñòc chæ cuûa node keá tieáp hay node tröôùc
noù.
noù.
 Danh saùch lieân keát laø caáu truùc döõ lieäu ñoäng,
Danh saùch lieân keát laø caáu truùc döõ lieäu ñoäng,
coù theå theâm hay huûy node cuûa danh saùch trong
coù theå theâm hay huûy node cuûa danh saùch trong
khi chay chöông trình. Vôùi caùch caøi ñaët caùc thao
khi chay chöông trình. Vôùi caùch caøi ñaët caùc thao
taùc theâm hay huûy node ta chæ caàn thay ñoåi laïi
taùc theâm hay huûy node ta chæ caàn thay ñoåi laïi
vuøng lieân keát cho phuø hôïp.
vuøng lieân keát cho phuø hôïp.
 Tuy nhieân, vieäc löu tröõ danh saùch lieân keát toán
Tuy nhieân, vieäc löu tröõ danh saùch lieân keát toán
boä nhôù hôn anh saùch keà vì moãi node cuûa danh
boä nhôù hôn anh saùch keà vì moãi node cuûa danh
saùch phaûi chöùa theâm vuøng lieân keát. Ngoaøi ra
saùch phaûi chöùa theâm vuøng lieân keát. Ngoaøi ra
vieäc truy xuaát node thöù I trong danh saùch lieân
vieäc truy xuaát node thöù I trong danh saùch lieân
keát chaäm hôn vì phaûi duyeät töø ñaàu danh saùch.
keát chaäm hôn vì phaûi duyeät töø ñaàu danh saùch.
22
 Có
Có nhiều
nhiều kiểu
kiểu tổ
tổ chức
chức liên
liên kết
kết giữa
giữa các
các phần
phần
tử
tử trong
trong danh
danh sách
sách như
như :
:
 Danh
Danh sách
sách liên
liên kết
kết đơn
đơn
 Danh
Danh sách
sách liên
liên kết
kết kép
kép
 Danh
Danh sách
sách liên
liên kết
kết vòng
vòng
 …
…
Danh
Danh sách
sách liên
liên kết
kết (
(List
List)
)
23
Danh
Danh sách
sách liên
liên kết
kết (
(List
List)
)
 Danh
Danh sách
sách liên
liên kết
kết đơn
đơn:
: mỗi
mỗi phần
phần tử
tử liên
liên kết
kết với
với phần
phần tử
tử
đứng
đứng sau
sau nó
nó trong
trong danh
danh sách
sách:
:
 Danh
Danh sách
sách liên
liên kết
kết kép
kép:
: mỗi
mỗi phần
phần tử
tử liên
liên kết
kết với
với các
các phần
phần
tử
tử đứng
đứng trước
trước và
và sau
sau nó
nó trong
trong danh
danh sách
sách:
:
A B X Z Y
A B C D
24
Danh
Danh sách
sách liên
liên kết
kết (
(List
List)
)
 Danh
Danh sách
sách liên
liên kết
kết vòng
vòng :
: phần
phần tử
tử cuối
cuối danh
danh sách
sách liên
liên kết
kết
với
với phần
phần tử
tử đầu
đầu danh
danh sách
sách:
:
A B X Z Y
A B C D
Danh
Danh sách liên kết đơn
sách liên kết đơn
(
(xâu
xâu đơn
đơn)
)
26
DSLK - định nghĩa
DSLK - định nghĩa
 DSLK đơn là chuỗi các node, được tổ chức theo thứ tự
DSLK đơn là chuỗi các node, được tổ chức theo thứ tự
tuyến tính
tuyến tính
 Mỗi node gồm 2 phần:
Mỗi node gồm 2 phần:
 Phần Data, information :
Phần Data, information : löu tröõ caùc thoâng tin
löu tröõ caùc thoâng tin
veà baûn thaân phaàn töû .
veà baûn thaân phaàn töû .
 Phần link hay con trỏ :
Phần link hay con trỏ : löu tröõ ñòa chæ cuûa
löu tröõ ñòa chæ cuûa
phaàn töû keá tieáp trong danh saùch, hoaëc
phaàn töû keá tieáp trong danh saùch, hoaëc
löu tröõ giaù trò NULL neáu laø phaàn töû
löu tröõ giaù trò NULL neáu laø phaàn töû
cuoái danh saùch.
cuoái danh saùch.
Data Link
Node
27
typedef struct Node
{
int data; // Data là kiểu đã định nghĩa trước
Node * link; //con trỏ chỉ đến cấu trúc NODE
};
Cấu trúc dữ liệu của DSLK đơn
Cấu trúc dữ liệu của DSLK đơn
28
Lưu trữ DSLK đơn trong RAM
Lưu trữ DSLK đơn trong RAM
100
Joe
140
Bill
500
Marta
NULL
Sahra
140
Kock
230
Addres
Addres
s
s
Name
Name Age
Age Link
Link
100
100 Joe
Joe 20
20 140
140
110
110 Bill
Bill 42
42 500
500
140
140 Marta
Marta 27
27 110
110
230
230 Sahra
Sahra 25
25 NULL
NULL
…
… …
… …
…
500
500 Koch
Koch 31
31 230
230
 Ví dụ : Ta có danh sách theo dạng bảng sau
Ta có danh sách theo dạng bảng sau
110
230
500
140
Địa chỉ
000
…
29
DSLK đơn truy xuất – Minh họa
DSLK đơn truy xuất – Minh họa
 VD:
VD:
‘Joe’ 140 ‘Marta’ 110
‘Bill’ 500 ‘Koch’ 230
100
100 140
110 500
Đ a ch
ị ỉ
first
‘Bill’ NULL
230
30
Tổ
Tổ chức
chức,
, quản
quản lý
lý
 Để
Để quản
quản lý
lý một
một xâu
xâu đơn
đơn chỉ
chỉ cần
cần biết
biết địa
địa chỉ
chỉ phần
phần tử
tử đầu
đầu xâu
xâu.
.
 Con
Con trỏ
trỏ First
First sẽ
sẽ được
được dùng
dùng để
để lưu
lưu trữ
trữ địa
địa chỉ
chỉ phần
phần tử
tử đầu
đầu
xâu
xâu,
, ta
ta gọi
gọi First là
là đầu
đầu xâu
xâu.
. Ta
Ta có
có khai
khai báo
báo :
:
NODE* first;
 Để
Để tiện
tiện lợi
lợi,
, có
có thể
thể sử
sử dụng
dụng thêm
thêm một
một con
con trỏ
trỏ last giữ
giữ địa
địa chỉ
chỉ
phần
phần tử
tử cuối
cuối xâu
xâu.
. Khai
Khai báo
báo last như
như sau
sau :
:
NODE* last;
A B X Z Y
first
last
31
DSLK – Khai báo phần Data
DSLK – Khai báo phần Data
typedef struct node
{
DataType data;
struct node * link;
}NODE;
typedef struct node
{
int data;
struct node * link;
}NODE;
typedef struct node
{
SinhVien data;
struct node * link;
}NODE;
C u trúc
ấ
node
DataType ?
32
Khai
Khai báo
báo kiểu
kiểu của
của 1
1 phần
phần tử
tử và
và kiểu
kiểu danh
danh sách
sách liên
liên kết
kết đơn và để đơn
đơn và để đơn
giản ta xét mỗi node gồm vùng chứa dữ liệu là kiểu số nguyên
giản ta xét mỗi node gồm vùng chứa dữ liệu là kiểu số nguyên :
:
// kiểu của một phần tử trong danh sách
typedef struct Node
{
int data;
NODE * link;
}NODE;
typedef struct List // kiểu danh sách liên kết
{
NODE* first;
NODE* last;
}LIST;
Trong thực tế biến data là một kiểu struct
Tổ
Tổ chức
chức,
, quản
quản lý
lý
33
 Thủ
Thủ tục
tục GetNode để
để tạo
tạo ra
ra một
một phần
phần tử
tử cho
cho danh
danh sách
sách với
với thông
thông tin
tin
chứa
chứa trong
trong x
x
NODE* GetNode(int x)
{
NODE *p;
// Cấp phát vùng nhớ cho phần tử
p = (NODE*)malloc(sizeof(NODE))//p= new NODE;
if (p==NULL)
{
cout<<“Khong du bo nho!”; exit(1);
}
p->data = x; // Gán thông tin cho phần tử p
p->link = NULL;
return p;
}
Tạo
Tạo một
một phần
phần tử
tử
34
Để
Để tạo
tạo một
một phần
phần tử
tử mới
mới cho
cho danh
danh sách
sách,
, cần
cần thực
thực hiện
hiện câu
câu lệnh
lệnh:
:
new_ele = GetNode(x);

 new
new_
_ele
ele sẽ
sẽ quản
quản lý
lý địa
địa chỉ
chỉ của
của phần
phần tử
tử mới
mới được
được tạo
tạo.
.
Tạo
Tạo một
một phần
phần tử
tử
35
 Tạo
Tạo danh
danh sách
sách rỗng
rỗng
 Thêm
Thêm một
một phần
phần tử
tử vào
vào danh
danh sách
sách
 Tìm
Tìm kiếm
kiếm một
một giá
giá trị
trị trên
trên danh
danh sách
sách
 Trích
Trích một
một phần
phần tử
tử ra
ra khỏi
khỏi danh
danh sách
sách
 Duyệt
Duyệt danh
danh sách
sách
 Hủy
Hủy toàn
toàn bộ
bộ danh
danh sách
sách
Các
Các thao
thao tác
tác cơ
cơ sở
sở
36
void
void Init
Init(
(LIST
LIST &l)
&l)
{
{
l.first = l.last = NULL;
l.first = l.last = NULL;
}
}
Khởi
Khởi tạo
tạo danh
danh sách
sách rỗng
rỗng
first
last
37
Có 3 vị trí thêm phần tử mới vào danh sách :
Có 3 vị trí thêm phần tử mới vào danh sách :
 Thêm
Thêm vào
vào đầu
đầu danh
danh sách
sách
 Nối
Nối vào
vào cuối
cuối danh
danh sách
sách
 Chèn
Chèn vào
vào danh
danh sách
sách sau
sau một
một phần
phần tử
tử q
q
Thêm
Thêm một
một phần
phần tử
tử
38
first
last
X
new_ele
Thêm
Thêm một
một phần
phần tử
tử
39
A B C D E
first
last
Thêm
Thêm một
một phần
phần tử
tử vào
vào đầu
đầu
X
new_ele
40
//input: danh sách (first, last), phần tử mới new_ele
//input: danh sách (first, last), phần tử mới new_ele
//output: danh sách (first, last) với new_ele ở đầu DS
//output: danh sách (first, last) với new_ele ở đầu DS
 Nếu
Nếu Danh sách rỗng
Danh sách rỗng Thì
Thì
 first = new_ele;
first = new_ele;
 last = first;
last = first;
 Ngược lại
Ngược lại
 new_ele ->link = first;
new_ele ->link = first;
 first = new_ele ;
first = new_ele ;
Thêm
Thêm một
một phần
phần tử
tử vào
vào đầu
đầu
41
void AddFirst(LIST &l, NODE* new_ele)
{
if (l.first == NULL) //Xâu rỗng
{
l.first = new_ele;
l.last = l.first;
}
else
{
new_ele->link = l.first;
l.first = new_ele;
}
}
Thêm
Thêm một
một phần
phần tử
tử vào
vào đầu
đầu
42
//
//input
input:
: danh
danh sách
sách (first,
(first, last
last),
), thành
thành phần
phần dữ
dữ liệu
liệu X
X
//
//output
output:
: danh
danh sách
sách (first,
(first, last
last)
) với
với phần
phần tử
tử chứa
chứa X
X ở
ở đầu
đầu DS
DS
 Tạo
Tạo phần
phần tử
tử mới
mới new
new_
_ele
ele để
để chứa
chứa dữ
dữ liệu
liệu X
X
 Nếu
Nếu tạo
tạo được
được:
:
Thêm
Thêm new
new_
_ele
ele vào
vào đầu
đầu danh
danh sách
sách
 Ngược
Ngược lại
lại
Báo
Báo lỗi
lỗi
Thêm
Thêm một
một thành
thành phần
phần dữ
dữ liệu
liệu vào
vào đầu
đầu
43
NODE* Insertfirst(LIST &l, int x)
{
NODE* new_ele = GetNode(x);
if (new_ele == NULL)
return NULL;
AddFirst(l, new_ele);
return new_ele;
}
Thêm
Thêm một
một thành
thành phần
phần dữ
dữ liệu
liệu vào
vào đầu
đầu
44
void
void create_list_first
create_list_first(
(LIST
LIST &l,
&l, int
int x)
x)
{
{
NODE
NODE *p;
*p;
int n;
int n;
cout
cout<<“Nhap so phan tu:”;
<<“Nhap so phan tu:”;
cin
cin>>n;
>>n;
for
for (
(int
int i=1;i<=n;i++)
i=1;i<=n;i++) // nen dung vong lap do while de viet
// nen dung vong lap do while de viet
{
{
//
//Insertfirst
Insertfirst(l,x);
(l,x);
p=
p=GetNode
GetNode(x);
(x);
AddFirst
AddFirst(l,p);
(l,p);
}
}
}
}
Tạo Link list bằng cách thêm vào đầu
Tạo Link list bằng cách thêm vào đầu
45
A B C D E
first
last
Thêm
Thêm một
một phần
phần tử
tử vào
vào cuối
cuối
X
new_ele
46
//
//input
input:
: danh
danh sách
sách (first,
(first, last
last),
), phần
phần tử
tử mới
mới new
new_
_ele
ele
//
//output
output:
: danh
danh sách
sách (first,
(first, last
last)
) với
với new
new_
_ele
ele ở
ở cu
cuố
ối
i DS
DS
 Nếu
Nếu Danh sách rỗng
Danh sách rỗng Thì
Thì
 first = new_ele;
first = new_ele;
 last = first;
last = first;
 Ngược lại
Ngược lại
 last->link = new_ele ;
last->link = new_ele ;
 last = new_ele ;
last = new_ele ;
Thêm
Thêm một
một phần
phần tử
tử vào
vào cuối
cuối
47
void InsertLast(LIST &l, NODE *new_ele)
{
if (l.first==NULL)
{
l.first = new_ele;
l.last = l.first;
}
else
{
l.last->link = new_ele;
l.last = new_ele ;
}
}
Thêm
Thêm một
một phần
phần tử
tử vào
vào cuối
cuối
48
//
//input
input:
: danh
danh sách
sách (first,
(first, last
last),
), thành
thành phần
phần dữ
dữ liệu
liệu X
X
//
//output
output:
: danh
danh sách
sách (first,
(first, last
last)
) với
với phần
phần tử
tử chứa
chứa X
X ở
ở cuối
cuối DS
DS
 Tạo
Tạo phần
phần tử
tử mới
mới new
new_
_ele
ele để
để chứa
chứa dữ
dữ liệu
liệu X
X
 Nếu
Nếu tạo
tạo được
được:
:
Thêm
Thêm new
new_
_ele
ele vào
vào cuối
cuối danh
danh sách
sách
 Ngược
Ngược lại
lại
Báo
Báo lỗi
lỗi
Thêm
Thêm một
một thành
thành phần
phần dữ
dữ liệu
liệu vào
vào cuối
cuối
49
NODE* InputLast(LIST &l)
{ int x,n;
printf(“Nhap so phan tu :”);
scanf(“%d”,&n);
for(int i=0;i<n;i++)
{
printf(“Nhap phan tu thu %d :”,i);
scanf(“%d”,&x);
NODE* p=GetNode(x);
InsertLast(l, new_ele);
}
}
Thêm
Thêm một
một thành
thành phần
phần dữ
dữ liệu
liệu vào
vào cuối
cuối
50
void
void create_list_last
create_list_last(
(list
list &l,
&l, int
int x)
x)
{
{
node
node *p;
*p;
int n;
int n;
cout
cout<<“Nhap so phan tu:”;
<<“Nhap so phan tu:”;
cin
cin>>n;
>>n;
for
for (
(int
int i=1;i<=n;i++)
i=1;i<=n;i++) // nen dung vong lap do while de viet
// nen dung vong lap do while de viet
{
{
p=
p=GetNode
GetNode(x);
(x);
InsertLast(
InsertLast(l,p);
l,p);
}
}
}
}
Tạo Link list bằng cách thêm vào cuối
Tạo Link list bằng cách thêm vào cuối
51
A B C D E
first
last
Chèn
Chèn một
một phần
phần tử
tử sau
sau q
q
X
new_ele
q
52
//
//input
input:
: danh
danh sách
sách (first,
(first, last
last),
), q
q,
, phần
phần tử
tử mới
mới new
new_
_ele
ele
//
//output
output:
: danh
danh sách
sách (first,
(first, last
last)
) với
với new
new_
_ele
ele ở
ở sau
sau q
q
Nếu
Nếu (
( q
q !=
!= NULL
NULL)
) thì
thì
new
new_
_ele
ele -> link =
-> link = q
q -> link;
-> link;
q
q -> link =
-> link = new
new_
_ele
ele ;
;
Nếu
Nếu (
( q
q ==last)
==last) thì
thì
last
last =
= new
new_
_ele
ele;
;
Ngược
Ngược lại
lại
Thêm
Thêm new
new_
_ele
ele vào
vào đầu
đầu danh
danh sách
sách
Chèn
Chèn một
một phần
phần tử
tử sau
sau q
q
53
void InsertAfter(LIST &l,NODE *q, NODE* new_ele)
{
if (q!=NULL && new_ele !=NULL)
{
new_ele->link = q->link;
q->link = new_ele;
if(q == l.last)
l.last = new_ele;
}
}
Chèn
Chèn một
một phần
phần tử
tử sau
sau q
q
54
 Duyệt
Duyệt danh
danh sách
sách là
là thao
thao tác
tác thường
thường được
được thực
thực hiện
hiện khi
khi có
có
nhu
nhu cầu
cầu xử
xử lý
lý các
các phần
phần tử
tử của
của danh
danh sách
sách theo
theo cùng
cùng một
một
cách
cách thức
thức hoặc
hoặc khi
khi cần
cần lấy
lấy thông
thông tin
tin tổng
tổng hợp
hợp từ
từ các
các phần
phần
tử
tử của
của danh
danh sách
sách như
như:
:
 Đếm
Đếm các
các phần
phần tử
tử của
của danh
danh sách
sách,
,
 Tìm
Tìm tất
tất cả
cả các
các phần
phần tử
tử thoả
thoả điều
điều kiện
kiện,
,
 Hủy
Hủy toàn
toàn bộ
bộ danh
danh sách
sách (
(và
và giải
giải phóng
phóng bộ
bộ nhớ
nhớ)
)
Duyệt
Duyệt danh
danh sách
sách
55
 Bước 1: p = first;
Bước 1: p = first; //Cho p trỏ đến phần tử đầu danh sách
//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
Bước 2: Trong khi (Danh sách chưa hết) thực hiện
 B21 : Xử lý phần tử p;
B21 : Xử lý phần tử p;
 B22 : p:=p->link;
B22 : p:=p->link; // Cho p trỏ tới phần tử kế
// Cho p trỏ tới phần tử kế
void ProcessList (LIST &l)
{
NODE *p;
p = l.first;
while (p!= NULL){
ProcessNode(p); // xử lý cụ thể tùy ứng dụng
p = p->link;
}
}
Duyệt
Duyệt danh
danh sách
sách
56
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
first
p
57
p =first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
3000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
58
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
3000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
59
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
3000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
60
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
5000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
61
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
5000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
62
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
5000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
63
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
4000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
64
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
4000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
65
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
4000
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
66
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
NULL
first
p
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
67
p = first;
while (p!=NULL)
{
printf
printf(“%dt”,p->data);
(“%dt”,p->data);
p = p->link;
}
3000 “Tran
Tran” 5000 “Ngoc
Ngoc” 4000 “Thao
Thao” NULL
3000 5000 4000
NULL
first
p
K t thúc
ế
DSLK – Minh họa in danh sách
DSLK – Minh họa in danh sách
68
In các phần tử trong danh sách
In các phần tử trong danh sách
void
void Output
Output(
(LIST
LIST l)
l)
{
{
NODE*
NODE* p=l.first;
p=l.first;
while
while(p!=
(p!=NULL
NULL)
)
{
{
cout<<p->data<<“t”;
cout<<p->data<<“t”;
p=p ->link;
p=p ->link;
}
}
cout<<endl;
cout<<endl;
}
}
69
Tìm kiếm một phần tử có khóa x
Tìm kiếm một phần tử có khóa x
NODE*
NODE* Search
Search(
(LIST
LIST l , int x)
l , int x)
{
{
NODE*
NODE* p=l.first;
p=l.first;
while
while( p!=
( p!=NULL
NULL && p->data!=x)
&& p->data!=x)
p=p->link;
p=p->link;
return
return p;
p;
}
}
70
Xóa một node của danh sách
Xóa một node của danh sách
Xóa node đầu của danh sách
Xóa node đầu của danh sách
Để xóa node đầu danh sách l (khác rỗng)
Để xóa node đầu danh sách l (khác rỗng)
 Gọi p là node đầu của danh sách (là l.first)
Gọi p là node đầu của danh sách (là l.first)
 Cho l.first trỏ vào node sau node p (là p->link)
Cho l.first trỏ vào node sau node p (là p->link)
 Nếu danh sách trở tahnh2 rỗng thì l.last=NULL
Nếu danh sách trở tahnh2 rỗng thì l.last=NULL
 Giải phóng vùng nhớ mà p trỏ tới
Giải phóng vùng nhớ mà p trỏ tới
71
Xóa một node của danh sách
Xóa một node của danh sách
A B C D E
first
last
p
72
void
void RemoveFirst
RemoveFirst(
(LIST
LIST &l)
&l)
{
{
if
if(l.first !=
(l.first != NULL
NULL)
)
{
{
NODE*
NODE* p=l.first;
p=l.first;
l.first=p->link;
l.first=p->link;
if
if(l.first ==
(l.first == NULL
NULL) l.last=
) l.last=NULL
NULL;//Nếu danh sách rỗng
;//Nếu danh sách rỗng
free
free(p);
(p);
}
}
}
}
Xóa một node của danh sách
Xóa một node của danh sách
73
Xóa node sau node q trong danh sách
Xóa node sau node q trong danh sách
Điều kiện để có thể xóa được node sau q là :
Điều kiện để có thể xóa được node sau q là :
 q phải khác NULL
q phải khác NULL
 Node sau q phải khác NULL
Node sau q phải khác NULL
Có 3 thao tác
Có 3 thao tác
 Gọi p là node sau q
Gọi p là node sau q
 Cho vùng link của q trỏ vào node đứng sau p (là l.link)
Cho vùng link của q trỏ vào node đứng sau p (là l.link)
 Nếu p là phần tử cuối thì l.last trỏ vào q
Nếu p là phần tử cuối thì l.last trỏ vào q
 Giải phóng vùng nhớ mà p trỏ tới
Giải phóng vùng nhớ mà p trỏ tới
Xóa một node của danh sách
Xóa một node của danh sách
74
Xóa node sau node q trong danh sách
Xóa node sau node q trong danh sách
A B C D E
first
last
q p
75
void
void RemoveAfter
RemoveAfter(
(LIST
LIST &l,
&l, NODE
NODE *q )
*q )
{
{
if
if(q !=
(q !=NULL
NULL && q->link !=
&& q->link !=NULL
NULL)
)
{
{
NODE
NODE* p = q->link;
* p = q->link;
q->link = p->link;
q->link = p->link;
if
if(p==l.last)
(p==l.last) l.last=q;
l.last=q;
free
free(p);
(p);
}
}
}
}
Xóa node sau node q trong danh sách
Xóa node sau node q trong danh sách
76
 Để
Để h
hủ
ủy
y toàn
toàn bộ
bộ danh
danh sách
sách,
, thao
thao tác
tác xử
xử lý
lý bao
bao gồm
gồm hành
hành
động
động giải
giải phóng
phóng một
một phần
phần tử
tử,
, do
do vậy
vậy phải
phải cập
cập nhật
nhật các
các
liên
liên kết
kết liên
liên quan
quan:
:
 Bước
Bước 1:
1: Trong
Trong khi
khi (
(Danh
Danh sách
sách chưa
chưa hết
hết)
) thực
thực hiện
hiện
 B
B11:
11:
 p
p = first;
= first;
 first =first->link;
first =first->link; //
// Cho
Cho p
p trỏ
trỏ tới
tới phần
phần tử
tử kế
kế
 B
B12:
12:
 Hủy
Hủy p
p;
;
 Bước
Bước 2:
2:
 last =
last = NULL
NULL;
;//
//Bảo
Bảo đảm
đảm tính
tính nhất
nhất quán
quán khi
khi xâu
xâu rỗng
rỗng
Hủy
Hủy toàn
toàn bộ
bộ danh
danh sách
sách
77
void RemoveList(LIST &l)
{
NODE *p;
while (l.first!= NULL) {
p = l.first;
l.first = p->link;
free( p);
}
l.last = NULL;
}
Hủy
Hủy toàn
toàn bộ
bộ danh
danh sách
sách
Sắp
Sắp xếp trên
xếp trên danh
danh sách
sách
liên kết đơn
liên kết đơn
79
Sắp
Sắp xếp
xếp danh
danh sách
sách
Cách
Cách tiếp
tiếp cận
cận:
:
 Phương án 1:
Phương án 1:
Hoán vị nội dung các phần tử trong danh sách
Hoán vị nội dung các phần tử trong danh sách
(thao tác trên vùng data).
(thao tác trên vùng data).
 Phương án 2 :
Phương án 2 :
Thay đổi các mối liên kết (thao tác trên vùng
Thay đổi các mối liên kết (thao tác trên vùng
link)
link)
80
Sắp
Sắp xếp
xếp danh
danh sách
sách
Hoán
Hoán vị
vị nội
nội dung
dung các
các phần
phần tử
tử trong
trong danh
danh sách
sách
 Cài
Cài đặt
đặt lại
lại trên
trên danh sách liên kết
danh sách liên kết một
một trong
trong những
những
thuật
thuật toán
toán sắp
sắp xếp
xếp đã
đã biết
biết trên
trên mảng
mảng
 Điểm
Điểm khác
khác biệt
biệt duy
duy nhất
nhất là
là cách
cách thức
thức truy
truy xuất
xuất đến
đến
các
các phần
phần tử
tử trên
trên danh sách liên kết
danh sách liên kết thông
thông qua
qua liên
liên kết
kết
thay
thay vì
vì chỉ
chỉ số
số như
như trên
trên mảng
mảng.
.
 Do
Do thực
thực hiện
hiện hoán
hoán vị
vị nội
nội dung
dung của
của các
các phần
phần tử
tử nên
nên
đòi
đòi hỏi
hỏi sử
sử dụng
dụng thêm
thêm vùng
vùng nhớ
nhớ trung
trung gian
gian 
 chỉ
chỉ thích
thích
hợp
hợp với
với các
các xâu
xâu có
có các
các phần
phần tử
tử có
có thành
thành phần
phần data
data
kích
kích thước
thước nhỏ
nhỏ.
.
 Khi
Khi kích
kích thước
thước của
của trường
trường data
data lớn
lớn,
, việc
việc hoán
hoán vị
vị giá
giá
trị
trị của
của hai
hai phân
phân tử
tử sẽ
sẽ chiếm
chiếm chi
chi phí
phí đáng
đáng kể
kể.
.
81
void
void SLL_InterChangeSort
SLL_InterChangeSort (
( List
List &l )
&l )
{
{
for
for (
( Node
Node* p=l.first ; p!=
* p=l.first ; p!=l.last
l.last ; p=p->link )
; p=p->link )
for
for (
( Node
Node* q=p->link ; q!=
* q=p->link ; q!=NULL
NULL ; q=q->link )
; q=q->link )
if
if ( p->data > q->data )
( p->data > q->data )
Swap
Swap( p->data , q->data );
( p->data , q->data );
}
}
Sắp xếp bằng phương pháp đổi
chổ trực tiếp ( Interchange Sort )
82
12 2 8 1 5
p
q
l.first
l.last
Sắp xếp đổi chổ trực tiếp
( Interchange Sort )
83
1 12 8 2 5
p
q
l.first
l.last
Sắp xếp đổi chổ trực tiếp
( Interchange Sort )
84
1 2 12 8 5
p
q
l.first
l.last
Sắp xếp đổi chổ trực tiếp
( Interchange Sort )
85
1 2 5 12 8
p
q
l.first
l.last
Sắp xếp đổi chổ trực tiếp
( Interchange Sort )
86
1 2 5 8 12
p
q
Dừng
l.first
l.last
Sắp xếp đổi chổ trực tiếp
( Interchange Sort )
87
Sắp xếp bằng phương pháp chọn trực tiếp
Sắp xếp bằng phương pháp chọn trực tiếp
(
( Selection sort
Selection sort )
)
void ListSelectionSort (LIST &l)
{
for ( Node* p = l.first ; p != l.last ; p = p->link )
{
Node* min = p;
for ( Node* q = p->link ; q != NULL ; q = q->link )
if ( min->data > q->data ) min = q ;
Swap(min->data, p->data);
}
}
88
12 2 8 1 5
p
min
l.first
l.last
Sắp xếp bằng phương pháp chọn trực tiếp
Sắp xếp bằng phương pháp chọn trực tiếp
(
( Selection sort
Selection sort )
)
89
1 2 8 12 5
p
min
l.first
l.last
Sắp xếp bằng phương pháp chọn trực tiếp
Sắp xếp bằng phương pháp chọn trực tiếp
(
( Selection sort
Selection sort )
)
90
1 2 8 12 5
p
min
l.first
l.last
Sắp xếp bằng phương pháp chọn trực tiếp
Sắp xếp bằng phương pháp chọn trực tiếp
(
( Selection sort
Selection sort )
)
91
1 2 5 12 8
p
min
l.first
l.last
Sắp xếp bằng phương pháp chọn trực tiếp
Sắp xếp bằng phương pháp chọn trực tiếp
(
( Selection sort
Selection sort )
)
92
1 2 5 8 12
p
min
l.first
l.last
Dừng
Sắp xếp bằng phương pháp chọn trực tiếp
Sắp xếp bằng phương pháp chọn trực tiếp
(
( Selection sort
Selection sort )
)
93
void
void SLL_BubleSort
SLL_BubleSort (
( List
List l )
l )
{
{
Node
Node* t =
* t = l.last
l.last ;
;
for
for (
( Node
Node* p =
* p = l.first
l.first ; p !=
; p != NULL
NULL ; p = p->link)
; p = p->link)
{
{ Node
Node* t1;
* t1;
for
for (
( Node
Node* q=
* q=l.first
l.first ; p!=t ; q=q->link )
; p!=t ; q=q->link )
{
{
if
if( q->data
( q->data >
> q->link->data )
q->link->data )
Swap
Swap( q->data
( q->data ,
, q->link->data );
q->link->data );
t1 = q ;
t1 = q ;
}
}
t = t1;
t = t1;
}
}
}
}
Sắp xếp bằng phương pháp nổi bọt
Sắp xếp bằng phương pháp nổi bọt
(
( Bubble
Bubble sort
sort )
)
94
12 2 8 1 5
q
q->link
l.first
l.last
Sắp xếp bằng phương pháp nổi bọt
Sắp xếp bằng phương pháp nổi bọt
(
( Bubble sort
Bubble sort )
)
95
2 8 1 5 12
q
q->link
l.first
l.last
Sắp xếp bằng phương pháp nổi bọt
Sắp xếp bằng phương pháp nổi bọt
(
( Bubble sort
Bubble sort )
)
96
2 1 5 8 12
q
q->link
l.first
l.last
Sắp xếp bằng phương pháp nổi bọt
Sắp xếp bằng phương pháp nổi bọt
(
( Bubble sort
Bubble sort )
)
97
1 2 5 8 12
q
q->link
l.first
l.last
Sắp xếp bằng phương pháp nổi bọt
Sắp xếp bằng phương pháp nổi bọt
(
( Bubble sort
Bubble sort )
)
98
1 2 5 8 12
l.first
l.last
Dừng
Sắp xếp bằng phương pháp nổi bọt
Sắp xếp bằng phương pháp nổi bọt
(
( Bubble sort
Bubble sort )
)
99
Sắp
Sắp xếp
xếp Thay
Thay đổi
đổi các
các mối
mối liên
liên kết
kết
 Thay vì hoán đổi giá trị, ta sẽ tìm cách thay đổi trình tự móc
Thay vì hoán đổi giá trị, ta sẽ tìm cách thay đổi trình tự móc
nối của các phần tử sao cho tạo lập nên được thứ tự mong
nối của các phần tử sao cho tạo lập nên được thứ tự mong
muốn
muốn 
 chỉ thao tác trên các móc nối (link).
chỉ thao tác trên các móc nối (link).
 Kích thước của trường link:
Kích thước của trường link:
 Không phụ thuộc vào bản chất dữ liệu lưu trong xâu
Không phụ thuộc vào bản chất dữ liệu lưu trong xâu
 Bằng kích thước 1 con trỏ (2 hoặc 4 byte trong môi
Bằng kích thước 1 con trỏ (2 hoặc 4 byte trong môi
trường 16 bit, 4 hoặc 8 byte trong môi trường 32 bit…)
trường 16 bit, 4 hoặc 8 byte trong môi trường 32 bit…)
 Thao tác trên các móc nối thường phức tạp hơn thao tác trực
Thao tác trên các móc nối thường phức tạp hơn thao tác trực
tiếp trên dữ liệu.
tiếp trên dữ liệu.

Cần cân nhắc khi chọn cách tiếp cận: Nếu dữ liệu không quá
Cần cân nhắc khi chọn cách tiếp cận: Nếu dữ liệu không quá
lớn thì nên chọn phương án 1 hoặc một thuật toán hiệu quả
lớn thì nên chọn phương án 1 hoặc một thuật toán hiệu quả
nào đó.
nào đó.
100
Phương pháp lấy
Phương pháp lấy Node
Node ra khỏi danh
ra khỏi danh
sách giữ nguyên địa chỉ của
sách giữ nguyên địa chỉ của Node
Node
12 2 5 1
q
8
p
1 . q->link = p->link ; // p->link chứa địa chỉ sau p
2 . q->link = NULL ; // p không liên kết phần tử Node
101
Quick Sort : Thuật toán
Quick Sort : Thuật toán
//input: xâu (first, last)
//input: xâu (first, last)
//output: xâu đã được sắp tăng dần
//output: xâu đã được sắp tăng dần
 Bước 1: Nếu xâu có ít hơn 2 phần tử
Bước 1: Nếu xâu có ít hơn 2 phần tử
Dừng;
Dừng; //xâu đã có thứ tự
//xâu đã có thứ tự
 Bước 2: Chọn X là phần tử đầu xâu L làm ngưỡng. Trích X ra
Bước 2: Chọn X là phần tử đầu xâu L làm ngưỡng. Trích X ra
khỏi L.
khỏi L.
 Bước 3: Tách xâu L ra làm 2 xâu L
Bước 3: Tách xâu L ra làm 2 xâu L1
1 (gồm các phần tử nhỏ hơn
(gồm các phần tử nhỏ hơn
hay bằng X) và L
hay bằng X) và L2
2 (gồm các phần tử lớn hơn X).
(gồm các phần tử lớn hơn X).
 Bước 4: Sắp xếp
Bước 4: Sắp xếp Quick Sort
Quick Sort (L
(L1
1).
).
 Bước 5: Sắp xếp
Bước 5: Sắp xếp Quick Sort
Quick Sort (L
(L2
2).
).
 Bước 6: Nối L
Bước 6: Nối L1
1, X, và L
, X, và L2
2 lại theo trình tự ta có xâu L đã được
lại theo trình tự ta có xâu L đã được
sắp xếp.
sắp xếp.
102
Sắp
Sắp xếp
xếp quick
quick sort
sort
first
6
8
2
4
5
1
103
Quick
Quick sort
sort :
: phân
phân hoạch
hoạch
first
6
8
2
4
5
1
X
Chọn phần tử đầu xâu làm ngưỡng
104
Quick
Quick sort
sort :
: phân
phân hoạch
hoạch
first
6
8
2
4
5
1
X
Tách xâu hiện hành thành 2 xâu
first1
first2
105
Quick
Quick sort
sort :
: phân
phân hoạch
hoạch
first
6
8
2
4
5
1
X
Tách xâu hiện hành thành 2 xâu
first1
first2
106
Quick
Quick sort
sort :
: phân
phân hoạch
hoạch
first
6
8
2
4
5
1
X
Tách xâu hiện hành thành 2 xâu
first1
first2
107
Quick
Quick sort
sort :
: phân
phân hoạch
hoạch
first
6
8
2
4
5
1
X
Tách xâu hiện hành thành 2 xâu
first1
first2
108
Quick
Quick sort
sort
first
6
8
2
4
5
1
X
Sắp xếp các xâu l1, l2
first1
first2
109
Quick
Quick sort
sort
first
6
8
2
4
5
1
X
Nối l1, X, l2
first1
first2
Đưa kết quả vào first
110
void SListAppend(SLIST &l, LIST &l2)
{
if (l2.first == NULL) return;
if (l.first == NULL)
l = l2;
else {
l.first->link = l2.first;
l.last = l2.last;
}
Init(l2);
}
Nối 2 danh sách
Nối 2 danh sách
111
void SListQSort(SLIST &l) {
NODE *X, *p;
SLIST l1, l2;
if (list.first == list.last) return;
Init(l1); Init(l2);
X = l.first; l.first=x->link;
while (l.first != NULL) {
p = l.first;
if (p->data <= X->data) AddFirst(l1, p);
else AddFirst(l2, p);
}
SListQSort(l1); SListQSort(l2);
SListAppend(l, l1);
AddFirst(l, X);
SListAppend(l, l2);
}
112
 Nhận
Nhận xét
xét:
:
 Quick
Quick sort
sort trên
trên xâu
xâu đơn
đơn đơn
đơn giản
giản hơn
hơn phiên
phiên bản
bản của
của nó
nó
trên
trên mảng
mảng một
một chiều
chiều
 Khi
Khi dùng
dùng quick
quick sort
sort sắp
sắp xếp
xếp một
một xâu
xâu đơn
đơn,
, chỉ
chỉ có
có một
một
chọn
chọn lựa
lựa phần
phần tử
tử cầm
cầm canh
canh duy
duy nhất
nhất hợp
hợp lý
lý là
là phần
phần tử
tử
đầu
đầu xâu
xâu.
. Chọn
Chọn bất
bất kỳ
kỳ phần
phần tử
tử nào
nào khác
khác cũng
cũng làm
làm tăng
tăng
chi
chi phí
phí một
một cách
cách không
không cần
cần thiết
thiết do
do cấu
cấu trúc
trúc tự
tự nhiên
nhiên
của
của xâu
xâu.
.
Quick
Quick sort
sort :
: nhận
nhận xét
xét
Danh
Danh sách hạn chế
sách hạn chế
Stack ( Ngăn xếp )
Stack ( Ngăn xếp )
Queue
Queue (
( Hàng
Hàng đợi
đợi )
)
Stack
Stack
115
Stack
Stack
 Stack
Stack là
là một
một vật
vật chứa
chứa (
(container
container)
) các
các đối
đối tượng
tượng làm
làm việc
việc theo
theo
cơ
cơ chế
chế LIFO
LIFO (
(Last
Last In
In First
First Out
Out)
) 
 Việc
Việc thêm
thêm một
một đối
đối tượng
tượng
vào
vào stack
stack hoặc
hoặc lấy
lấy một
một đối
đối tượng
tượng ra
ra khỏi
khỏi stack
stack được
được thực
thực hiện
hiện
theo
theo cơ
cơ chế
chế “
“Vào sau ra
Vào sau ra trước”
trước”.
.
 Các
Các đối
đối tượng
tượng có
có thể
thể được
được thêm
thêm vào
vào stack
stack bất
bất kỳ
kỳ lúc
lúc nào
nào
nhưng
nhưng chỉ
chỉ có
có đối
đối tượng
tượng thêm
thêm vào
vào sau
sau cùng
cùng mới
mới được
được phép
phép lấy
lấy
ra
ra khỏi
khỏi stack
stack.
.
 “
“Push”
Push”:
: Thao
Thao tác
tác thêm
thêm 1
1 đối
đối tượng
tượng vào
vào stack
stack
 “
“Pop”
Pop”:
: Thao
Thao tác
tác lấy
lấy 1
1 đối
đối tượng
tượng ra
ra khỏi
khỏi stack
stack.
.
 Stack
Stack có
có nhiều
nhiều ứng
ứng dụng
dụng:
: khử
khử đệ
đệ qui
qui,
, tổ
tổ chức
chức lưu
lưu vết
vết các
các quá
quá
trình
trình tìm
tìm kiếm
kiếm theo
theo chiều
chiều sâu
sâu và
và quay
quay lui
lui,
, vét
vét cạn
cạn,
, ứng
ứng dụng
dụng
trong
trong các
các bài
bài toán
toán tính
tính toán
toán biểu
biểu thức
thức,
, …
…
116
Gi
Giới thiệu
ới thiệu
 LIFO: Last In First Out
LIFO: Last In First Out
 Thao tác Pop, Push chỉ diễn ra ở 1 đầu
Thao tác Pop, Push chỉ diễn ra ở 1 đầu
117
Hi
Hiện thực stack
ện thực stack
(
(Implementation of a Stack
Implementation of a Stack )
)
Mảng 1 chiều Danh sách LK
Kích thước stack
khi quá thiếu, lúc
quá thừa
Cấp phát
động!
Push / Pop hơi
phức tạp
Push/Pop
khá dễ
dàng
118
Stack ( Ngăn xếp )
Stack ( Ngăn xếp )
 Stack
Stack là
là một
một CTDL
CTDL trừu
trừu tượng
tượng tuyến
tuyến tính
tính hỗ
hỗ trợ
trợ 2
2 thao
thao
tác
tác chính
chính:
:
 Push
Push(
(o
o):
): Thêm
Thêm đối
đối tượng
tượng o
o vào
vào đầu
đầu stack
stack
 Pop
Pop():
():Lấy
Lấy đối
đối tượng
tượng ở
ở đầu
đầu stack
stack ra
ra khỏi
khỏi stack
stack và
và trả
trả
về
về giá
giá trị
trị của
của nó
nó.
. Nếu
Nếu stack
stack rỗng
rỗng thì
thì lỗi
lỗi sẽ
sẽ xảy
xảy ra
ra.
.
 Stack
Stack cũng
cũng hỗ
hỗ trợ
trợ một
một số
số thao
thao tác
tác khác
khác:
:
 isEmpty
isEmpty():
(): Kiểm
Kiểm tra
tra xem
xem stack
stack có
có rỗng
rỗng không
không.
.
 Top
Top():
(): Trả
Trả về
về giá
giá trị
trị của
của phần
phần tử
tử nằm
nằm ở
ở đầu
đầu stack
stack
mà
mà không
không hủy
hủy nó
nó khỏi
khỏi stack
stack.
. Nếu
Nếu stack
stack rỗng
rỗng thì
thì lỗi
lỗi
sẽ
sẽ xảy
xảy ra
ra.
.
119
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
(
(Array Implementation of a Stack)
Array Implementation of a Stack)
 Có
Có thể
thể tạo
tạo một
một stack
stack bằng
bằng cách
cách khai
khai báo
báo một
một mảng
mảng 1
1
chiều
chiều với
với kích
kích thước
thước tối
tối đa
đa là
là N
N (
(ví
ví dụ
dụ:
: N
N =1000).
=1000).
 Stack
Stack có
có thể
thể chứa
chứa tối
tối đa
đa N
N phần
phần tử
tử đánh
đánh số
số từ
từ 0
0 đến
đến N
N-1.
-1.
 Phần
Phần tử
tử nằm
nằm ở
ở đầu
đầu stack
stack sẽ
sẽ có
có chỉ
chỉ số
số t
t (
(lúc
lúc đó
đó trong
trong stack
stack
đang
đang chứa
chứa t
t+1
+1 phần
phần tử
tử)
)
 Để
Để khai
khai báo
báo một
một stack
stack,
, ta
ta cần
cần một
một mảng
mảng 1
1 chiều
chiều S
S,
, biến
biến
nguyên
nguyên t
t cho
cho biết
biết chỉ
chỉ số
số của
của đầu
đầu stack
stack và
và hằng
hằng số
số N
N cho
cho
biết
biết kích
kích thước
thước tối
tối đa
đa của
của stack
stack.
.
Data S [N];
int t;
120
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
 Lệnh
Lệnh top
top = 0
= 0 sẽ
sẽ tạo
tạo ra
ra một
một stack
stack S
S rỗng
rỗng.
.
 Giá
Giá trị
trị của
của t
t sẽ
sẽ cho
cho biết
biết số
số phần
phần tử
tử hiện
hiện hành
hành có
có
trong
trong stack
stack.
.
 Khi
Khi cài
cài đặt
đặt bằng
bằng mảng
mảng 1
1 chiều
chiều,
, stack
stack có
có kích
kích thước
thước
tối
tối đa
đa nên
nên cần
cần xây
xây dựng
dựng thêm
thêm một
một thao
thao tác
tác phụ
phụ cho
cho
stack
stack:
:
 Full
Full():
(): Kiểm
Kiểm tra
tra xem
xem stack
stack có
có đầy
đầy chưa
chưa.
.
 Khi
Khi stack
stack đầy
đầy,
, việc
việc gọi
gọi đến
đến hàm
hàm push
push()
() sẽ
sẽ phát
phát
sinh
sinh ra
ra lỗi
lỗi.
.
121
Khai báo stack
Khai báo stack
typedef struct
typedef struct node
node
{
{
int
int data;
data;
};
};
typedef struct
typedef struct stack
stack
{
{
int
int top;
top;
node
node list[N];
list[N];
};
};
122
 Khởi tạo Stack:
Khởi tạo Stack:
void
void Init
Init(
(stack
stack &s)
&s)
{
{
s.top=0;
s.top=0;
}
}
Biểu diễn Stack dùng mảng
Biểu diễn Stack dùng mảng
123
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
 Kiểm
Kiểm tra
tra stack
stack rỗng
rỗng hay
hay không
không
int Empty(stack s)
{
if(s.top==0)
return 1;
return 0;
}
124
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
 Kiểm
Kiểm tra
tra stack
stack đầy
đầy hay
hay không
không
int Full(stack s)
{
if(s.top==N-1)
return 1;
return 0;
}
125
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
 Thêm
Thêm một
một phần
phần tử
tử x
x vào
vào stack
stack S
S
void Push(stack &s,node x)
{
if(!Full(s)) // stack chưa
đầy
s.list[++s.top]=x;
}
126
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
 Trích
Trích thông
thông tin
tin và
và huỷ
huỷ phần
phần tử
tử ở
ở đỉnh
đỉnh stack
stack S
S
node Pop(stack &s)
{
node n;
if(!Empty(s)) // stack khác r?ng
{
n=s.list[s.top];
s.top--;
}
return n;
}
127
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng mảng
mảng
 Nhận
Nhận xét
xét:
:
 Các
Các thao
thao tác
tác trên
trên đều
đều làm
làm việc
việc với
với chi
chi phí
phí O
O(1).
(1).
 Việc
Việc cài
cài đặt
đặt stack
stack thông
thông qua
qua mảng
mảng một
một chiều
chiều
đơn
đơn giản
giản và
và khá
khá hiệu
hiệu quả
quả.
.
 Tuy
Tuy nhiên
nhiên,
, hạn
hạn chế
chế lớn
lớn nhất
nhất của
của phương
phương án
án cài
cài
đặt
đặt này
này là
là giới
giới hạn
hạn về
về kích
kích thước
thước của
của stack
stack N
N.
.
Giá
Giá trị
trị của
của N
N có
có thể
thể quá
quá nhỏ
nhỏ so
so với
với nhu
nhu cầu
cầu
thực
thực tế
tế hoặc
hoặc quá
quá lớn
lớn sẽ
sẽ làm
làm lãng
lãng phí
phí bộ
bộ nhớ
nhớ.
.
128
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng danh
danh sách
sách liên
liên kết
kết
(
(Implementation of a Stack Using Linked
Implementation of a Stack Using Linked
Representation)
Representation)
 Có
Có thể
thể tạo
tạo một
một stack
stack bằng
bằng cách
cách sử
sử dụng
dụng một
một danh
danh
sách
sách liên
liên kết
kết đơn
đơn (
(DSLK
DSLK).
).
 DSLK
DSLK có
có những
những đặc
đặc tính
tính rất
rất phù
phù hợp
hợp để
để dùng
dùng làm
làm
stack
stack vì
vì mọi
mọi thao
thao tác
tác trên
trên stack
stack đều
đều diễn
diễn ra
ra ở
ở đầu
đầu
stack
stack.
.
stack
stack *s;
129
Khai báo stack
Khai báo stack
typedef struct
typedef struct node
node
{
{
int
int data;
data;
node *link;
node *link;
};
};
typedef struct
typedef struct stack
stack
{
{
node
node *top;
*top;
};
};
130
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng danh
danh sách
sách liên
liên kết
kết
 Khôûi taïo stack
Khôûi taïo stack
void
void Init
Init(
(stack
stack &t)
&t)
{
{
t.top=NULL;
t.top=NULL;
}
}
131
Biểu
Biểu diễn
diễn Stack
Stack dùng
dùng danh
danh sách
sách liên
liên kết
kết
 Kiểm
Kiểm tra
tra stack
stack rỗng
rỗng :
:
int Empty(stack t)
{
return t.top == NULL ? 1 :
0; // stack rỗng
}
132
 Thêm
Thêm một
một phần
phần tử
tử x
x vào
vào stack
stack S
S
void
void Push
Push(stack &t, int x){
(stack &t, int x){
node
node *p=
*p=new
new node;
node;
if
if(p!=NULL){
(p!=NULL){
p->data=x;
p->data=x;
p->link=NULL;
p->link=NULL;
if
if(
(Empty
Empty(t))
(t))
t.top=p;
t.top=p;
else
else{
{
p->link=t.top;
p->link=t.top;
t.top=p;
t.top=p;
}
}
}
}
}
}
133
•Trích thông tin và huỷ phần tử ở đỉnh stack S
Trích thông tin và huỷ phần tử ở đỉnh stack S
int
int Pop
Pop(stack &t)
(stack &t)
{
{
node
node *p;
*p;
int x;
int x;
if
if(!
(!Empty
Empty(t))
(t))
{
{
p=t.top;
p=t.top;
t.top=p->link;
t.top=p->link;
x=p->data;
x=p->data;
free(p);
free(p);
return
return x;
x;
}
}
}
}
134
Ứng
Ứng dụng
dụng của
của Stack
Stack
 Stack
Stack thích
thích hợp
hợp lưu
lưu trữ
trữ các
các loại
loại dữ
dữ liệu
liệu mà
mà trình
trình tự
tự truy
truy
xuất
xuất ngược
ngược với
với trình
trình tự
tự lưu
lưu trữ
trữ
 Một
Một số
số ứng
ứng dụng
dụng của
của Stack
Stack:
:
 Trong
Trong trình
trình biên
biên dịch
dịch (
(thông
thông dịch
dịch),
), khi
khi thực
thực hiện
hiện các
các
thủ
thủ tục
tục,
, Stack
Stack được
được sử
sử dụng
dụng để
để lưu
lưu môi
môi trường
trường của
của
các
các thủ
thủ tục
tục.
.
 Lưu
Lưu dữ
dữ liệu
liệu khi
khi giải
giải một
một số
số bài
bài toán
toán của
của lý
lý thuyết
thuyết đồ
đồ
thị
thị (
(như
như tìm
tìm đường
đường đi
đi)
)
 Khử
Khử đệ
đệ qui
qui
 ...
...
135
Ứng
Ứng dụng
dụng của
của Stack
Stack
Ví
Ví du
du:
:ï
ï thủ
thủ tục
tục Quick
Quick_
_Sort
Sort dùng
dùng Stack
Stack để
để khử
khử đệ
đệ qui
qui:
:
 1.
1. l
l:=1;
:=1; r
r:=
:=n
n;
;
 2.
2. Chọn
Chọn phần
phần tử
tử giữa
giữa x
x:=
:=a
a[(
[(l
l+
+r
r)
) div
div 2];
2];
 3.
3. Phân
Phân hoạch
hoạch (
(l
l,
,r
r)
) thành
thành (
(l
l1,
1,r
r1)
1) và
và (
(l
l2,
2,r
r2)
2) bằng
bằng cách
cách xét
xét:
:
 y
y thuộc
thuộc (
(l
l1,
1,r
r1)
1) nếu
nếu y
y
x
x;
;
 y
y thuộc
thuộc (
(l
l2,
2,r
r2)
2) ngược
ngược lại
lại;
;
 4.
4. Nếu
Nếu phân
phân hoạch
hoạch (
(l
l2,
2,r
r2)
2) có
có nhiều
nhiều hơn
hơn 1
1 phần
phần tử
tử thực
thực hiện
hiện:
:
 Cất
Cất (
(l
l2,
2,r
r2)
2) vào
vào Stack
Stack;
;
 Nếu
Nếu (
(l
l1,
1,r
r1)
1) có
có nhiều
nhiều hơn
hơn 1
1 phần
phần tử
tử thực
thực hiện
hiện:
:
 l
l=
=l
l1;
1;
 r
r=
=r
r1;
1;
 Goto
Goto 2;
2;
 Ngược
Ngược lại
lại
 Lấy
Lấy (
(l
l,
,r
r)
) ra
ra khỏi
khỏi Stack
Stack nếu
nếu Stack
Stack khác
khác rỗng
rỗng và
và Goto
Goto 2;
2;
 Nếu
Nếu không
không dừng
dừng;
;
Hàng
Hàng đợi
đợi (
( Queue
Queue)
)
137
Hàng
Hàng đợi
đợi (
( Queue
Queue)
)
 Hàng
Hàng đợi
đợi là
là một
một vật
vật chứa
chứa (
(container
container)
) các
các đối
đối
tượng
tượng làm
làm việc
việc theo
theo cơ
cơ chế
chế FIFO
FIFO (
(First
First In
In First
First
Out
Out)
) 
 việc
việc thêm
thêm một
một đối
đối tượng
tượng vào
vào hàng
hàng đợi
đợi
hoặc
hoặc lấy
lấy một
một đối
đối tượng
tượng ra
ra khỏi
khỏi hàng
hàng đợi
đợi được
được
thực
thực hiện
hiện theo
theo cơ
cơ chế
chế “Vào
“Vào trước
trước ra
ra trước”
trước”.
.
 Các
Các đối
đối tượng
tượng có
có thể
thể được
được thêm
thêm vào
vào hàng
hàng đợi
đợi bất
bất
kỳ
kỳ lúc
lúc nào
nào nhưng
nhưng chỉ
chỉ có
có đối
đối tượng
tượng thêm
thêm vào
vào đầu
đầu
tiên
tiên mới
mới được
được phép
phép lấy
lấy ra
ra khỏi
khỏi hàng
hàng đợi
đợi.
.
138
Hàng
Hàng đợi
đợi (
( Queue
Queue)
)
139
Giới thiệu
Giới thiệu
 FIFO
FIFO
 Thêm vào cuối và lấy ra ở đầu
Thêm vào cuối và lấy ra ở đầu
 Trong
Trong tin
tin học
học,
, CTDL
CTDL hàng
hàng đợi
đợi có
có nhiều
nhiều ứng
ứng dụng
dụng:
: khử
khử đệ
đệ
qui
qui,
, tổ
tổ chức
chức lưu
lưu vết
vết các
các quá
quá trình
trình tìm
tìm kiếm
kiếm theo
theo chiều
chiều rộng
rộng
và
và quay
quay lui
lui,
, vét
vét cạn
cạn,
, tổ
tổ chức
chức quản
quản lý
lý và
và phân
phân phối
phối tiến
tiến
trình
trình trong
trong các
các hệ
hệ điều
điều hành
hành,
, tổ
tổ chức
chức bộ
bộ đệm
đệm bàn
bàn phím
phím,
, …
…
140
Hàng
Hàng đợi
đợi (
( Queue
Queue)
)
 Hàng
Hàng đợi
đợi hỗ
hỗ trợ
trợ các
các thao
thao tác
tác:
:
 EnQueue(
(o
o):
):Thêm
Thêm đối
đối tượng
tượng o
o vào
vào cuối
cuối hàng
hàng đợi
đợi
 DeQueue():
(): Lấy
Lấy đối
đối tượng
tượng ở
ở đầu
đầu queue
queue ra
ra khỏi
khỏi
hàng
hàng đợi
đợi và
và trả
trả về
về giá
giá trị
trị của
của nó
nó.
. Nếu
Nếu hàng
hàng đợi
đợi
rỗng
rỗng thì
thì lỗi
lỗi sẽ
sẽ xảy
xảy ra
ra.
.
 Empty():
(): Kiểm
Kiểm tra
tra xem
xem hàng
hàng đợi
đợi có
có rỗng
rỗng không
không.
.
 Front():
(): Trả
Trả về
về giá
giá trị
trị của
của phần
phần tử
tử nằm
nằm ở
ở đầu
đầu
hàng
hàng đợi
đợi mà
mà không
không hủy
hủy nó
nó.
. Nếu
Nếu hàng
hàng đợi
đợi rỗng
rỗng thì
thì
lỗi
lỗi sẽ
sẽ xảy
xảy ra
ra.
.
141
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Có
Có thể
thể tạo
tạo một
một hàng
hàng đợi
đợi bằng
bằng cách
cách sử
sử dụng
dụng một
một
mảng
mảng 1
1 chiều
chiều với
với kích
kích thước
thước tối
tối đa
đa là
là N
N (
(ví
ví dụ
dụ,
,
N
N=1000)
=1000) theo
theo kiểu
kiểu xoay
xoay vòng
vòng (
(coi
coi phần
phần tử
tử an
an-1
-1 kề
kề
với
với phần
phần tử
tử a
a0
0)
) 
 Hàng
Hàng đợi
đợi chứa
chứa tối
tối đa
đa N
N phần
phần tử
tử.
.
 Phần
Phần tử
tử ở
ở đầu
đầu hàng
hàng đợi
đợi (
(front
front element
element)
) sẽ
sẽ có
có chỉ
chỉ
số
số f
f.
.
 Phần
Phần tử
tử ở
ở cuối
cuối hàng
hàng đợi
đợi (
(rear
rear element
element)
) sẽ
sẽ có
có chỉ
chỉ
số
số r
r .
.
142
 Dùng một array: Có xu hướng dời về cuối array
Dùng một array: Có xu hướng dời về cuối array
 Hai cách hiện thực đầu tiên:
Hai cách hiện thực đầu tiên:
 Khi lấy một phần tử ra thì đồng thời dời hàng lên một vị trí.
Khi lấy một phần tử ra thì đồng thời dời hàng lên một vị trí.
 Chỉ dời hàng về đầu khi cuối hàng không còn chỗ
Chỉ dời hàng về đầu khi cuối hàng không còn chỗ
A B C D B C D B C D E
Ban đầu Lấy ra 1 phần tử:
dời tất cả về trước
Thêm vào 1 phần tử
A B C D B C D B C D E
Ban đầu Lấy ra 1 phần tử Thêm vào 1 phần tử:
dời tất cả về trước để
trống chỗ thêm vào
Biểu diễn Queue dùng mảng
Biểu diễn Queue dùng mảng
143
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Để
Để khai
khai báo
báo một
một hàng
hàng đợi
đợi,
, ta
ta cần
cần:
:
 một
một mảng
mảng một
một chiều
chiều Q
Q,
,
 hai
hai biến
biến nguyên
nguyên f
f,
, r
r cho
cho biết
biết chỉ
chỉ số
số của
của đầu
đầu và
và cuối
cuối của
của
hàng
hàng đợi
đợi
 hằng
hằng số
số N
N cho
cho biết
biết kích
kích thước
thước tối
tối đa
đa của
của hàng
hàng đợi
đợi.
.
 Ngoài
Ngoài ra
ra,
, khi
khi dùng
dùng mảng
mảng biểu
biểu diễn
diễn hàng
hàng đợi
đợi,
, cần
cần dùng
dùng
một
một giá
giá trị
trị đặc
đặc biệt
biệt,
, ký
ký hiệu
hiệu là
là NULLDATA
NULLDATA,
, để
để gán
gán cho
cho
những
những ô
ô còn
còn trống
trống trên
trên hàng
hàng đợi
đợi.
. Giá
Giá trị
trị này
này là
là một
một giá
giá trị
trị
nằm
nằm ngoài
ngoài miền
miền xác
xác định
định của
của dữ
dữ liệu
liệu lưu
lưu trong
trong hàng
hàng đợi
đợi..
..
144
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Trạng
Trạng thái
thái hàng
hàng đợi
đợi lúc
lúc bình
bình thường
thường:
:
 Trạng
Trạng thái
thái hàng
hàng đợi
đợi lúc
lúc xoay
xoay vòng
vòng:
:
145
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Hàng
Hàng đợi
đợi có
có thể
thể được
được khai
khai báo
báo cụ
cụ thể
thể như
như sau
sau:
:
typedef struct node
{
int data;
};
typedef struct queue
{
int front, rear;
node list[N];
};
 Do
Do khi
khi cài
cài đặt
đặt bằng
bằng mảng
mảng một
một chiều
chiều,
, hàng
hàng đợi
đợi có
có kích
kích thước
thước tối
tối đa
đa
nên
nên cần
cần xây
xây dựng
dựng thêm
thêm một
một thao
thao tác
tác phụ
phụ cho
cho hàng
hàng đợi
đợi:
:
 Full():
(): Kiểm
Kiểm tra
tra xem
xem hàng
hàng đợi
đợi có
có đầy
đầy chưa
chưa.
.
146
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Tạo
Tạo hàng
hàng đợi
đợi rỗng
rỗng
void Init(queue &q)
{
q.front = q.rear = 0;
}
 Kiểm tra queue rỗng
int Empty(queue q)
{
if(q.front == q.rear == 0)
return 1;
return 0;
}
147
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Kiểm
Kiểm tra
tra hàng
hàng đợi
đợi đầy
đầy hay
hay không
không
int Full(queue q)
{
if( q.front== 0 && q.rear== N-1) return 1;
if( q.front == q.rear+1) return 1;
return 0;
}
148
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Thêm
Thêm một
một phần
phần tử
tử x
x vào
vào cuối
cuối hàng
hàng đợi
đợi Q
Q
void EnQueue(queue &q, node x)
{
if(!Full(q)) //Queue chưa đầy
{
if(Empty(q) // Queue rỗng
q.front=q.rear=0;
else
if( q.rear==N-1) q.rear=0;
else q.rear++;
q.list[q.rear]=x;
}
}
149
Biểu
Biểu diễn
diễn Queue
Queue dùng
dùng mảng
mảng
 Trích
Trích,
, huỷ
huỷ phần
phần tử
tử ở
ở đầu
đầu hàng
hàng đợi
đợi Q
Q
node DeQueue(queue &q)
{
if(!Empty(q))
{
node t=q.list[q.front];
if(q.front == q.rear) Init(q);
else
if(q.fornt == N -1) q.front = 0;
else q.front++;
return t;
}
}
150
Biểu
Biểu diễn
diễn hàng
hàng đợi
đợi
dùng
dùng danh
danh sách
sách liên
liên kết
kết
 Có
Có thể
thể tạo
tạo một
một hàng
hàng đợi
đợi sử
sử dụng
dụng một
một DSLK
DSLK đơn
đơn.
.
 Phần
Phần tử
tử đầu
đầu DSKL
DSKL (
(head
head)
) sẽ
sẽ là
là phần
phần tử
tử đầu
đầu hàng
hàng đợi
đợi,
, phần
phần
tử
tử cuối
cuối DSKL
DSKL (
(tail
tail)
) sẽ
sẽ là
là phần
phần tử
tử cuối
cuối hàng
hàng đợi
đợi.
.
a1 a2 aN-2 an-1
Ñaàu
haøng
Cuoái
haøng
a0
151
typedef struct
typedef struct node
node
{
{
int
int data;
data;
node
node *link;
*link;
};
};
typedef struct
typedef struct queue
queue
{
{
node
node *front, *rear;
*front, *rear;
};
};
Biểu diễn hàng đợi
Biểu diễn hàng đợi
dùng danh sách liên kết
dùng danh sách liên kết
152
 Tạo hàng đợi rỗng:
Tạo hàng đợi rỗng:
void Init(queue &q)
{
q.front=q.rear= NULL;
}
}
 Kiểm tra hàng đợi rỗng :
Kiểm tra hàng đợi rỗng :
int Empty(queue &q)
{
if (q.front == NULL) return
1; // hàng đợi rỗng
else return 0;
}
153
 Thêm một phần tử p vào cuối hàng đợi
Thêm một phần tử p vào cuối hàng đợi
void EnQueue(queue &q, node *new_ele)
{
if(q.front == NULL)
{
q.front=new_ele;
q.rear=new_ele;
}
else
{
q.rear->link=new_ele;
q.rear=new_ele;
}
}
154
 Trích
Trích phần
phần tử
tử ở
ở đầu
đầu hàng
hàng đợi
đợi
node* DeQueue(queue &q)
{
if (!Empty(q))
{
node *p=q.front;
q.front=p->link;
return p
}
}
Biểu diễn hàng đợi
Biểu diễn hàng đợi
dùng danh sách liên kết
dùng danh sách liên kết
155
Biểu
Biểu diễn
diễn hàng
hàng đợi
đợi
dùng
dùng danh
danh sách
sách liên
liên kết
kết
 Nhận
Nhận xét
xét:
:
 Các
Các thao
thao tác
tác trên
trên hàng
hàng đợi
đợi biểu
biểu diễn
diễn bằng
bằng danh
danh sách
sách
liên
liên kết
kết làm
làm việc
việc với
với chi
chi phí
phí O
O(1).
(1).
 Nếu
Nếu không
không quản
quản lý
lý phần
phần tử
tử cuối
cuối xâu
xâu,
, thao
thao tác
tác Dequeue
sẽ
sẽ có
có độ
độ phức
phức tạp
tạp O
O(
(n
n).
).
156
Ứng
Ứng dụng
dụng của
của hàng
hàng đợi
đợi
 Hàng
Hàng đợi
đợi có
có thể
thể được
được sử
sử dụng
dụng trong
trong một
một số
số bài
bài toán
toán:
:
 Bài
Bài toán
toán ‘sản
‘sản xuất
xuất và
và tiêu
tiêu thụ’
thụ’ (
(ứng
ứng dụng
dụng trong
trong các
các hệ
hệ
điều
điều hành
hành song
song song
song).
).
 Bộ
Bộ đệm
đệm (
(ví
ví dụ
dụ:
: Nhấn
Nhấn phím
phím 
 Bộ
Bộ đệm
đệm 
 CPU
CPU xử
xử lý
lý).
).
 Xử
Xử lý
lý các
các lệnh
lệnh trong
trong máy
máy tính
tính (
(ứng
ứng dụng
dụng trong
trong HĐH
HĐH,
,
trình
trình biên
biên dịch
dịch),
), hàng
hàng đợi
đợi các
các tiến
tiến trình
trình chờ
chờ được
được xử
xử lý
lý,
,
…
….
.
Ứng dụng STACK để khử đệ
Ứng dụng STACK để khử đệ
quy cho bài toán tháp Hà Nội
quy cho bài toán tháp Hà Nội
158
Bài toán Tháp Hà nội
Bài toán Tháp Hà nội
 Luật:
Luật:
 Di chuyển mỗi lần một đĩa
Di chuyển mỗi lần một đĩa
 Không được đặt đĩa lớn lên trên đĩa nhỏ
Không được đặt đĩa lớn lên trên đĩa nhỏ
159
Bài toán Tháp Hà nội – Thiết kế
Bài toán Tháp Hà nội – Thiết kế
hàm
hàm
 Hàm đệ qui:
Hàm đệ qui:
 Chuyển (count-1) đĩa trên đỉnh của cột start sang cột
Chuyển (count-1) đĩa trên đỉnh của cột start sang cột
temp
temp
 Chuyển 1 đĩa (cuối cùng) của cột start sang cột finish
Chuyển 1 đĩa (cuối cùng) của cột start sang cột finish
 Chuyển count-1 đĩa từ cột temp sang cột finish
Chuyển count-1 đĩa từ cột temp sang cột finish
magic
160
Bài toán Tháp Hà nội – Mã C++
Bài toán Tháp Hà nội – Mã C++
void move(int n, char start, char finish, char temp)
{
if (n > 0)
{
move(n − 1, start, temp, finish);
cout << "Move disk " << n << " from " ;
cout<< start << " to " << finish << "." <<
endl;
move(n − 1, temp, finish, start);
}
}

More Related Content

PPT
Danh Sach Lien Ket
PPT
Danhsachlienket -phpapp02
PPT
Cấu trúc dữ liệu động
PPT
Nmlt c12 quan_lybonho
PDF
Bài 2 : Các khái niệm và nguyên tắc cơ bản của NET Framework - NỀN TẢNG LẬP T...
PDF
Nmlt c12 quan_lybonho_in
PDF
C4 data structures
PDF
C4 data structures
Danh Sach Lien Ket
Danhsachlienket -phpapp02
Cấu trúc dữ liệu động
Nmlt c12 quan_lybonho
Bài 2 : Các khái niệm và nguyên tắc cơ bản của NET Framework - NỀN TẢNG LẬP T...
Nmlt c12 quan_lybonho_in
C4 data structures
C4 data structures

Similar to danh-sach-lien-ket_Cấu trúc dữ liệu và giải thuậ.ppt (20)

PDF
Ctdl lab01
PDF
Quan ly bo nho trong C#
PPT
Session 13
PPT
Session 13
PDF
Chuong1 c
PPT
Lesson01
PPT
Lesson01
PPT
Bttrinh tin hoc dai cuong
PDF
CacCauTrucDuLieuCoBan Mon cấu trúc dữ liệu và giải thuật
PPTX
Cấu Trúc Dữ Liệu_Baigiang4_Danh sách liên kết.pptx
PDF
Ctdl c1
PDF
Bai5 dsachlket
PDF
ctdl&amp;gt 05-list_kep
PDF
Cau truc dl_va_giai_thuat_bai1[1] - copy
PDF
Day hoc lt (aml)
PDF
C5 danhsachlienket
DOCX
Đề thi mẫu trắc nghiệm cấu trúc dữ liệu cà giải thuật
DOCX
Lappj trình hướng đối tượng
PDF
BÀI 2: Các khái niệm cơ bản của ngôn ngữ lập trình c++
PPTX
lap trinh huong doi tuong lap trinh huong doi tuonglap trinh huong doi tuongl...
Ctdl lab01
Quan ly bo nho trong C#
Session 13
Session 13
Chuong1 c
Lesson01
Lesson01
Bttrinh tin hoc dai cuong
CacCauTrucDuLieuCoBan Mon cấu trúc dữ liệu và giải thuật
Cấu Trúc Dữ Liệu_Baigiang4_Danh sách liên kết.pptx
Ctdl c1
Bai5 dsachlket
ctdl&amp;gt 05-list_kep
Cau truc dl_va_giai_thuat_bai1[1] - copy
Day hoc lt (aml)
C5 danhsachlienket
Đề thi mẫu trắc nghiệm cấu trúc dữ liệu cà giải thuật
Lappj trình hướng đối tượng
BÀI 2: Các khái niệm cơ bản của ngôn ngữ lập trình c++
lap trinh huong doi tuong lap trinh huong doi tuonglap trinh huong doi tuongl...
Ad

Recently uploaded (20)

PDF
BÀI TẬP BỔ TRỢ TIẾNG ANH I-LEARN SMART WORLD LỚP 10 BÁM SÁT NỘI DUNG SGK - PH...
PPTX
Rung chuông vàng về kiến thức tổng quan về giáo dục
PDF
Thong bao 128-DHPY (25.Ke hoach nhap hoc trinh do dai hoc (dot 1.2025)8.2025)...
PDF
GIÁO ÁN KẾ HOẠCH BÀI DẠY THỂ DỤC 10 BÓNG CHUYỀN - KẾT NỐI TRI THỨC CẢ NĂM THE...
PDF
10 phương pháp rèn luyên tâm trí vững vàng • Sống Vững Vàng #1
PDF
FULL TN LSĐ 2024 HUIT. LICH SU DANGGGGGG
PPTX
Báo cáo Brucella sữa - trọng nghĩa..pptx
PDF
BIỆN PHÁP PHÁT TRIỂN NĂNG LỰC HỌC TẬP MÔN HÓA HỌC CHO HỌC SINH THÔNG QUA DẠY ...
PDF
dfmnghjkdh hỳh fhtrydr. ỷey rỷtu dfyy ỳy rt y y ytyr t rty rt
PDF
Mua Hàng Cần Trở Thành Quản Lý Chuỗi Cung Ứng.pdf
PDF
TUYỂN CHỌN ĐỀ ÔN THI OLYMPIC 30 THÁNG 4 HÓA HỌC LỚP 10-11 CÁC NĂM 2006-2021 B...
PDF
BÀI GIẢNG POWERPOINT CHÍNH KHÓA THEO LESSON TIẾNG ANH 11 - HK1 - NĂM 2026 - G...
PDF
GIÁO ÁN KẾ HOẠCH BÀI DẠY THỂ DỤC 11 BÓNG RỔ - KẾT NỐI TRI THỨC CẢ NĂM THEO CÔ...
PDF
CĐHA GAN 1, Benh GAN KHU TRU, 04.2025.pdf
PPTX
THUÊ 2025 - CHƯƠNG 1 TỔNG QUANưqeqweqw.pptx
PDF
GIÁO ÁN KẾ HOẠCH BÀI DẠY THỂ DỤC 11 CẦU LÔNG - KẾT NỐI TRI THỨC CẢ NĂM THEO C...
PPT
CH4 1 Van bagggggggggggggggggggggggggggggn QH.ppt
PPTX
Nhận thức chung về vi phạm pháp luật bảo vệ môi trường
PDF
BÀI GIẢNG TÓM TẮT XÁC SUẤT THỐNG KÊ (KHÔNG CHUYÊN TOÁN, 2 TÍN CHỈ) - KHOA SƯ...
PPTX
Bai giảng ngữ văn Trai nghiem de truong thanh.pptx
BÀI TẬP BỔ TRỢ TIẾNG ANH I-LEARN SMART WORLD LỚP 10 BÁM SÁT NỘI DUNG SGK - PH...
Rung chuông vàng về kiến thức tổng quan về giáo dục
Thong bao 128-DHPY (25.Ke hoach nhap hoc trinh do dai hoc (dot 1.2025)8.2025)...
GIÁO ÁN KẾ HOẠCH BÀI DẠY THỂ DỤC 10 BÓNG CHUYỀN - KẾT NỐI TRI THỨC CẢ NĂM THE...
10 phương pháp rèn luyên tâm trí vững vàng • Sống Vững Vàng #1
FULL TN LSĐ 2024 HUIT. LICH SU DANGGGGGG
Báo cáo Brucella sữa - trọng nghĩa..pptx
BIỆN PHÁP PHÁT TRIỂN NĂNG LỰC HỌC TẬP MÔN HÓA HỌC CHO HỌC SINH THÔNG QUA DẠY ...
dfmnghjkdh hỳh fhtrydr. ỷey rỷtu dfyy ỳy rt y y ytyr t rty rt
Mua Hàng Cần Trở Thành Quản Lý Chuỗi Cung Ứng.pdf
TUYỂN CHỌN ĐỀ ÔN THI OLYMPIC 30 THÁNG 4 HÓA HỌC LỚP 10-11 CÁC NĂM 2006-2021 B...
BÀI GIẢNG POWERPOINT CHÍNH KHÓA THEO LESSON TIẾNG ANH 11 - HK1 - NĂM 2026 - G...
GIÁO ÁN KẾ HOẠCH BÀI DẠY THỂ DỤC 11 BÓNG RỔ - KẾT NỐI TRI THỨC CẢ NĂM THEO CÔ...
CĐHA GAN 1, Benh GAN KHU TRU, 04.2025.pdf
THUÊ 2025 - CHƯƠNG 1 TỔNG QUANưqeqweqw.pptx
GIÁO ÁN KẾ HOẠCH BÀI DẠY THỂ DỤC 11 CẦU LÔNG - KẾT NỐI TRI THỨC CẢ NĂM THEO C...
CH4 1 Van bagggggggggggggggggggggggggggggn QH.ppt
Nhận thức chung về vi phạm pháp luật bảo vệ môi trường
BÀI GIẢNG TÓM TẮT XÁC SUẤT THỐNG KÊ (KHÔNG CHUYÊN TOÁN, 2 TÍN CHỈ) - KHOA SƯ...
Bai giảng ngữ văn Trai nghiem de truong thanh.pptx
Ad

danh-sach-lien-ket_Cấu trúc dữ liệu và giải thuậ.ppt

  • 2. Cấu trúc dữ liệu động
  • 3. 3 Mục Mục tiêu tiêu  Giới Giới thiệu thiệu khái khái niệm niệm cấu cấu trúc trúc dữ dữ liệu liệu động động. .  Giới Giới thiệu thiệu danh danh sách sách liên liên kết kết: :  Các Các kiểu kiểu tổ tổ chức chức dữ dữ liệu liệu theo theo DSLK DSLK. .  Danh Danh sách sách liên liên kết kết đơn đơn: : tổ tổ chức chức, , các các thuật thuật toán toán, , ứng ứng dụng dụng. .
  • 4. 4 Kiểu Kiểu dữ dữ liệu liệu tĩnh tĩnh  Khái niệm : Một số đối tượng dữ liệu không thay thay đổi 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 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 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. 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 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 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 ký tự ... hoặc từ các cấu trúc đơn giản như mẩu tin, tập hợp, mảng ... hợp, mảng ...   Các đối tượng dữ liệu được xác định thuộc những kiểu dữ 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ó liệu này thường cứng ngắt, gò bó   khó diễn tả được thực khó diễn tả được thực tế vốn sinh động, phong phú. tế vốn sinh động, phong phú.
  • 5. 5 CTDL CTDL tĩnh tĩnh – – Một Một số số hạn hạn chế chế  Một Một số số đối đối tượng tượng dữ dữ liệu liệu trong trong chu chu kỳ kỳ sống sống của của nó nó có có thể thể thay thay đổi đổi về về cấu cấu trúc trúc, , độ độ lớn lớn, , như như danh danh sách sách các các học học viên viên trong trong một một lớp lớp học học có có thể thể tăng tăng thêm thêm, , giảm giảm đi đi ... ... Nếu Nếu dùng dùng những những cấu cấu trúc trúc dữ dữ liệu liệu tĩnh tĩnh đã đã biết biết như như mảng mảng để để biểu biểu diễn diễn   Những Những thao thao tác tác phức phức tạp tạp, , kém kém tự tự nhiên nhiên   chương chương trình trình khó khó đọc đọc, , khó khó bảo bảo trì trì và và nhất nhất là là khó khó có có thể thể sử sử dụng dụng bộ bộ nhớ nhớ một một cách cách có có hiệu hiệu quả quả. .  Dữ Dữ liệu liệu tĩnh tĩnh sẽ sẽ chiếm chiếm vùng vùng nhớ nhớ đã đã dành dành cho cho chúng chúng suốt suốt quá quá trình trình hoạt hoạt động động của của chương chương trình trình   sử sử dụng dụng bộ bộ nhớ nhớ kém kém hiệu hiệu quả quả. .
  • 6. 6 CTDL tĩnh CTDL tĩnh  Mảng 1 chiều Mảng 1 chiều  Kích thước cố định (fixed size) Kích thước cố định (fixed size)  Chèn 1 phần tử vào mảng rất khó 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 Các phần tử tuần tự theo chỉ số 0   n-1 n-1  Truy cập ngẫu nhiên (random access) Truy cập ngẫu nhiên (random access) 0 1 2 3 4 n-2 n-1 chèn
  • 7. 7 Cấu trúc dữ liệu động Cấu trúc dữ liệu động  Danh sách liên kết Danh sách liên kết  Cấp phát động lúc chạy chương trình 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ớ 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 Kích thước danh sách chỉ bị giới hạn do RAM  Thao tác thêm xoá đơn giản Thao tác thêm xoá đơn giản Insert, Delete
  • 8. 8 Hướng Hướng giải giải quyết quyết  Cần Cần xây xây dựng dựng cấu cấu trúc trúc dữ dữ liệu liệu đáp đáp ứng ứng được được các các yêu yêu cầu cầu: :  Linh Linh động động hơn hơn. .  Có Có thể thể thay thay đổi đổi kích kích thước thước, , cấu cấu trúc trúc trong trong suốt suốt thời thời gian gian sống sống. .   Cấu Cấu trúc trúc dữ dữ liệu liệu động động. .
  • 9. Danh sách liên kết Danh sách liên kết ( LINKED LIST ) ( LINKED LIST )
  • 10. 10 Biến Biến không không động động Biến Biến không không động động ( (biến biến tĩnh tĩnh, , biến biến nửa nửa tĩnh tĩnh) ) là là những những biến biến thỏa thỏa: :  Được Được khai khai báo báo tường tường minh minh, ,  Tồn Tồn tại tại khi khi vào vào phạm phạm vi vi khai khai báo báo và và chỉ chỉ mất mất khi khi ra ra khỏi khỏi phạm phạm vi vi này này, ,  Được Được cấp cấp phát phát vùng vùng nhớ nhớ trong trong vùng vùng dữ dữ liệu liệu ( (Data Data segment segment) ) hoặc hoặc là là Stack Stack ( (đối đối với với biến biến nửa nửa tĩnh tĩnh - - các các biến biến cục cục bộ bộ). ).  Kích Kích thước thước không không thay thay đổi đổi trong trong suốt suốt quá quá trình trình sống sống. .  Do Do được được khai khai báo báo tường tường minh minh, , các các biến biến không không động động có có một một định định danh danh đã đã được được kết kết nối nối với với địa địa chỉ chỉ vùng vùng nhớ nhớ lưu lưu trữ trữ biến biến và và được được truy truy xuất xuất trực trực tiếp tiếp thông thông qua qua định định danh danh đó đó. .  Ví Ví dụ dụ : : int a; // a, b là các biến không động char b[10];
  • 11. 11 Biến Biến động động  Trong Trong nhiều nhiều trường trường hợp hợp, , tại tại thời thời điểm điểm biên biên dịch dịch không không thể thể xác xác định định trước trước kích kích thước thước chính chính xác xác của của một một số số đối đối tượng tượng dữ dữ liệu liệu do do sự sự tồn tồn tại tại và và tăng tăng trưởng trưởng của của chúng chúng phụ phụ thuộc thuộc vào vào ngữ ngữ cảnh cảnh của của việc việc thực thực hiện hiện chương chương trình trình. .  Các Các đối đối tượng tượng dữ dữ liệu liệu có có đặc đặc điểm điểm kể kể trên trên nên nên được được khai khai báo báo như như biến biến động động. . Biến Biến động động là là những những biến biến thỏa thỏa: :  Biến Biến không không được được khai khai báo báo tường tường minh minh. .  Có Có thể thể được được cấp cấp phát phát hoặc hoặc giải giải phóng phóng bộ bộ nhớ nhớ khi khi người người sử sử dụng dụng yêu yêu cầu cầu. .  Các Các biến biến này này không không theo theo qui qui tắc tắc phạm phạm vi vi ( (tĩnh tĩnh). ).  Vùng Vùng nhớ nhớ của của biến biến được được cấp cấp phát phát trong trong Heap Heap. .  Kích Kích thước thước có có thể thể thay thay đổi đổi trong trong quá quá trình trình sống sống. .
  • 12. 12 Biến Biến động động  Do Do không không được được khai khai báo báo tường tường minh minh nên nên các các biến biến động động không không có có một một định định danh danh được được kết kết buộc buộc với với địa địa chỉ chỉ vùng vùng nhớ nhớ cấp cấp phát phát cho cho nó nó, , do do đó đó gặp gặp khó khó khăn khăn khi khi truy truy xuất xuất đến đến một một biến biến động động. .  Để Để giải giải quyết quyết vấn vấn đề đề, , biến biến con con trỏ trỏ ( (là là biến biến không không động động) ) được được sử sử dụng dụng để để trỏ trỏ đến đến biến biến động động. .  Khi Khi tạo tạo ra ra một một biến biến động động, , phải phải dùng dùng một một con con trỏ trỏ để để lưu lưu địa địa chỉ chỉ của của biến biến này này và và sau sau đó đó, , truy truy xuất xuất đến đến biến biến động động thông thông qua qua biến biến con con trỏ trỏ đã đã biết biết định định danh danh. .
  • 13. 13 Biến Biến động động  Hai Hai thao thao tác tác cơ cơ bản bản trên trên biến biến động động là là tạo tạo và và hủy hủy một một biến biến động động do do biến biến con con trỏ trỏ ‘p’ ‘p’ trỏ trỏ đến đến: :  Tạo Tạo ra ra một một biến biến động động và và cho cho con con trỏ trỏ ‘p’ ‘p’ chỉ chỉ đến đến nó nó  Hủy Hủy một một biến biến động động do do p p chỉ chỉ đến đến
  • 14. 14 Biến Biến động động  Tạo Tạo ra ra một một biến biến động động và và cho cho con con trỏ trỏ ‘p’ ‘p’ chỉ chỉ đến đến nó nó void* malloc(size); // // trả trả về về con con trỏ trỏ chỉ chỉ đến đến vùng vùng nhớ nhớ // // size size byte byte vừa vừa được được cấp cấp phát phát. . void* calloc(n,size);// // trả trả về về con con trỏ trỏ chỉ chỉ đến đến vùng vùng nhớ nhớ // // vừa vừa được được cấp cấp phát phát gồm gồm n n phần phần tử tử, , // // mỗi mỗi phần phần tử tử có có kích kích thước thước size size byte byte new // // toán toán tử tử cấp cấp phát phát bộ bộ nhớ nhớ trong trong C C++ ++  Hàm Hàm free free( (p p) ) huỷ huỷ vùng vùng nhớ nhớ cấp cấp phát phát bởi bởi hàm hàm malloc malloc hoặc hoặc calloc calloc do do p p trỏ trỏ tới tới  Toán Toán tử tử delete p p huỷ huỷ vùng vùng nhớ nhớ cấp cấp phát phát bởi bởi toán toán tử tử new do do p p trỏ trỏ tới tới
  • 15. 15 Biến Biến động động – – Ví Ví dụ dụ int *p1, *p2; // cấp phát vùng nhớ cho 1 biến động kiểu int p1 = (int*)malloc(sizeof(int)); *p1 = 5; // đặt giá trị 5 cho biến động đang được p1 quản lý // cấp phát biến động kiểu mảng gồm 10 phần tử kiểu int p2 = (int*)calloc(10, sizeof(int)); *(p2+3) = 0; // đặt giá trị 0 cho phần tử thứ 4 của mảng p2 free(p1); free(p2);
  • 16. 16 Kiểu Kiểu dữ dữ liệu liệu Con Con trỏ trỏ  Kiểu Kiểu con con trỏ trỏ là là kiểu kiểu cơ cơ sở sở dùng dùng lưu lưu địa địa chỉ chỉ của của một một đối đối tượng tượng dữ dữ liệu liệu khác khác. .  Biến Biến thuộc thuộc kiểu kiểu con con trỏ trỏ Tp Tp là là biến biến mà mà giá giá trị trị của của nó nó là là địa địa chỉ chỉ cuả cuả một một vùng vùng nhớ nhớ ứng ứng với với một một biến biến kiểu kiểu T T, , hoặc hoặc là là giá giá trị trị NULL NULL. .
  • 17. 17 Con Con trỏ trỏ – – Khai Khai báo báo  Cú Cú pháp pháp định định nghĩa nghĩa một một kiểu kiểu con con trỏ trỏ trong trong ngôn ngôn ngữ ngữ C C : : typedef <kiểu cơ sở> * < kiểu con trỏ>;  Ví Ví dụ dụ : : typedef int *intpointer; intpointer p; hoặc hoặc int *p; là là những những khai khai báo báo hợp hợp lệ lệ. .
  • 18. 18 Con Con trỏ trỏ – – Thao Thao tác tác căn căn bản bản  Các Các thao thao tác tác cơ cơ bản bản trên trên kiểu kiểu con con trỏ trỏ:( :(minh minh họa họa bằng bằng C C) )  Khi Khi 1 1 biến biến con con trỏ trỏ p p lưu lưu địa địa chỉ chỉ của của đối đối tượng tượng x x, , ta ta nói nói ‘p ‘p trỏ trỏ đến đến x’ x’. .  Gán Gán địa địa chỉ chỉ của của một một vùng vùng nhớ nhớ con con trỏ trỏ p p: : p p = < = <địa địa chỉ chỉ>; >; ví duï : ví duï : int i,* int i,*p; p; p=&i; p=&i;  Truy Truy xuất xuất nội nội dung dung của của đối đối tượng tượng do do p p trỏ trỏ đến đến (* (*p p) )
  • 19. 19 Danh Danh sách sách liên liên kết kết ( (List List) ) I. I. Định Định nghĩa nghĩa: : Moät danh saùch (list) laø moät taäp hôïp Moät danh saùch (list) laø moät taäp hôïp goàm moät soá höõu haïn phaàn töû goàm moät soá höõu haïn phaàn töû cuøng kieåu, coù thöù töï. cuøng kieåu, coù thöù töï. Coù hai caùch caøi ñaët danh saùch laø : Coù hai caùch caøi ñaët danh saùch laø :  Caøi ñaët theo kieåu keá tieáp : ta coù Caøi ñaët theo kieåu keá tieáp : ta coù danh saùch keà hay danh saùch ñaëc. danh saùch keà hay danh saùch ñaëc.  Caøi ñaët theo kieåu lieân keát : ta coù Caøi ñaët theo kieåu lieân keát : ta coù danh saùch lieân keát. danh saùch lieân keát.
  • 20. 20 Danh Danh sách sách liên liên kết kết ( (List List) ) a. a. Danh saùch keà : Danh saùch keà :  Caùc phaàn töû cuûa danh saùch goïi laø caùc node, Caùc phaàn töû cuûa danh saùch goïi laø caùc node, ñöôïc löu tröõ keà lieàn nhau trong boä nhôù. Moãi ñöôïc löu tröõ keà lieàn nhau trong boä nhôù. Moãi node coù theå laø moät giaù trò kieåu int, float, char, … node coù theå laø moät giaù trò kieåu int, float, char, … hoaëc coù theå laø moät struct vôùi nhieàu vuøng tin. hoaëc coù theå laø moät struct vôùi nhieàu vuøng tin. Maûng hay chuoãi laø daïng cuûa danh saùch keà. Maûng hay chuoãi laø daïng cuûa danh saùch keà.  Ñòa chæ cuûa moãi node trong danh saùch ñöôïc xaùc Ñòa chæ cuûa moãi node trong danh saùch ñöôïc xaùc ñònh baèng chæ soá (index). Chæ soá cuûa danh saùch ñònh baèng chæ soá (index). Chæ soá cuûa danh saùch laø moät soá nguyeân vaø ñöôïc ñaùnh töø 0 ñeán moät laø moät soá nguyeân vaø ñöôïc ñaùnh töø 0 ñeán moät giaù trò toái ña naøo ñoù. giaù trò toái ña naøo ñoù.  Danh saùch keà laø caáu truùc döõ lieäu tónh, soá node Danh saùch keà laø caáu truùc döõ lieäu tónh, soá node toái ña cuûa danh saùch keà coá ñònh sau khi caáp toái ña cuûa danh saùch keà coá ñònh sau khi caáp phaùt neân soá node caàn duøng coù khi thöøa hay phaùt neân soá node caàn duøng coù khi thöøa hay thieáu. Ngoaøi ra danh saùch keà khoâng phuø hôïp thieáu. Ngoaøi ra danh saùch keà khoâng phuø hôïp vôùi caùc thao taùc thöôøng xuyeân nhö theâm hay vôùi caùc thao taùc thöôøng xuyeân nhö theâm hay xoùa phaàn töû treân danh saùch, xoùa phaàn töû treân danh saùch,
  • 21. 21 Danh Danh sách sách liên liên kết kết ( (List List) ) b. b. Danh saùch lieân keát : Danh saùch lieân keát :  Caùc phaàn töû cuûa danh saùch goïi laø node, naèm Caùc phaàn töû cuûa danh saùch goïi laø node, naèm raûi raùc trong boä nhôù. Moãi node, ngoaøi vuøng raûi raùc trong boä nhôù. Moãi node, ngoaøi vuøng döõ lieäu thoâng thöôøng, coøn coù vuøng lieân keát döõ lieäu thoâng thöôøng, coøn coù vuøng lieân keát chöùa ñòc chæ cuûa node keá tieáp hay node tröôùc chöùa ñòc chæ cuûa node keá tieáp hay node tröôùc noù. noù.  Danh saùch lieân keát laø caáu truùc döõ lieäu ñoäng, Danh saùch lieân keát laø caáu truùc döõ lieäu ñoäng, coù theå theâm hay huûy node cuûa danh saùch trong coù theå theâm hay huûy node cuûa danh saùch trong khi chay chöông trình. Vôùi caùch caøi ñaët caùc thao khi chay chöông trình. Vôùi caùch caøi ñaët caùc thao taùc theâm hay huûy node ta chæ caàn thay ñoåi laïi taùc theâm hay huûy node ta chæ caàn thay ñoåi laïi vuøng lieân keát cho phuø hôïp. vuøng lieân keát cho phuø hôïp.  Tuy nhieân, vieäc löu tröõ danh saùch lieân keát toán Tuy nhieân, vieäc löu tröõ danh saùch lieân keát toán boä nhôù hôn anh saùch keà vì moãi node cuûa danh boä nhôù hôn anh saùch keà vì moãi node cuûa danh saùch phaûi chöùa theâm vuøng lieân keát. Ngoaøi ra saùch phaûi chöùa theâm vuøng lieân keát. Ngoaøi ra vieäc truy xuaát node thöù I trong danh saùch lieân vieäc truy xuaát node thöù I trong danh saùch lieân keát chaäm hôn vì phaûi duyeät töø ñaàu danh saùch. keát chaäm hôn vì phaûi duyeät töø ñaàu danh saùch.
  • 22. 22  Có Có nhiều nhiều kiểu kiểu tổ tổ chức chức liên liên kết kết giữa giữa các các phần phần tử tử trong trong danh danh sách sách như như : :  Danh Danh sách sách liên liên kết kết đơn đơn  Danh Danh sách sách liên liên kết kết kép kép  Danh Danh sách sách liên liên kết kết vòng vòng  … … Danh Danh sách sách liên liên kết kết ( (List List) )
  • 23. 23 Danh Danh sách sách liên liên kết kết ( (List List) )  Danh Danh sách sách liên liên kết kết đơn đơn: : mỗi mỗi phần phần tử tử liên liên kết kết với với phần phần tử tử đứng đứng sau sau nó nó trong trong danh danh sách sách: :  Danh Danh sách sách liên liên kết kết kép kép: : mỗi mỗi phần phần tử tử liên liên kết kết với với các các phần phần tử tử đứng đứng trước trước và và sau sau nó nó trong trong danh danh sách sách: : A B X Z Y A B C D
  • 24. 24 Danh Danh sách sách liên liên kết kết ( (List List) )  Danh Danh sách sách liên liên kết kết vòng vòng : : phần phần tử tử cuối cuối danh danh sách sách liên liên kết kết với với phần phần tử tử đầu đầu danh danh sách sách: : A B X Z Y A B C D
  • 25. Danh Danh sách liên kết đơn sách liên kết đơn ( (xâu xâu đơn đơn) )
  • 26. 26 DSLK - định nghĩa DSLK - định nghĩa  DSLK đơn là chuỗi các node, được tổ chức theo thứ tự DSLK đơn là chuỗi các node, được tổ chức theo thứ tự tuyến tính tuyến tính  Mỗi node gồm 2 phần: Mỗi node gồm 2 phần:  Phần Data, information : Phần Data, information : löu tröõ caùc thoâng tin löu tröõ caùc thoâng tin veà baûn thaân phaàn töû . veà baûn thaân phaàn töû .  Phần link hay con trỏ : Phần link hay con trỏ : löu tröõ ñòa chæ cuûa löu tröõ ñòa chæ cuûa phaàn töû keá tieáp trong danh saùch, hoaëc phaàn töû keá tieáp trong danh saùch, hoaëc löu tröõ giaù trò NULL neáu laø phaàn töû löu tröõ giaù trò NULL neáu laø phaàn töû cuoái danh saùch. cuoái danh saùch. Data Link Node
  • 27. 27 typedef struct Node { int data; // Data là kiểu đã định nghĩa trước Node * link; //con trỏ chỉ đến cấu trúc NODE }; Cấu trúc dữ liệu của DSLK đơn Cấu trúc dữ liệu của DSLK đơn
  • 28. 28 Lưu trữ DSLK đơn trong RAM Lưu trữ DSLK đơn trong RAM 100 Joe 140 Bill 500 Marta NULL Sahra 140 Kock 230 Addres Addres s s Name Name Age Age Link Link 100 100 Joe Joe 20 20 140 140 110 110 Bill Bill 42 42 500 500 140 140 Marta Marta 27 27 110 110 230 230 Sahra Sahra 25 25 NULL NULL … … … … … … 500 500 Koch Koch 31 31 230 230  Ví dụ : Ta có danh sách theo dạng bảng sau Ta có danh sách theo dạng bảng sau 110 230 500 140 Địa chỉ 000 …
  • 29. 29 DSLK đơn truy xuất – Minh họa DSLK đơn truy xuất – Minh họa  VD: VD: ‘Joe’ 140 ‘Marta’ 110 ‘Bill’ 500 ‘Koch’ 230 100 100 140 110 500 Đ a ch ị ỉ first ‘Bill’ NULL 230
  • 30. 30 Tổ Tổ chức chức, , quản quản lý lý  Để Để quản quản lý lý một một xâu xâu đơn đơn chỉ chỉ cần cần biết biết địa địa chỉ chỉ phần phần tử tử đầu đầu xâu xâu. .  Con Con trỏ trỏ First First sẽ sẽ được được dùng dùng để để lưu lưu trữ trữ địa địa chỉ chỉ phần phần tử tử đầu đầu xâu xâu, , ta ta gọi gọi First là là đầu đầu xâu xâu. . Ta Ta có có khai khai báo báo : : NODE* first;  Để Để tiện tiện lợi lợi, , có có thể thể sử sử dụng dụng thêm thêm một một con con trỏ trỏ last giữ giữ địa địa chỉ chỉ phần phần tử tử cuối cuối xâu xâu. . Khai Khai báo báo last như như sau sau : : NODE* last; A B X Z Y first last
  • 31. 31 DSLK – Khai báo phần Data DSLK – Khai báo phần Data typedef struct node { DataType data; struct node * link; }NODE; typedef struct node { int data; struct node * link; }NODE; typedef struct node { SinhVien data; struct node * link; }NODE; C u trúc ấ node DataType ?
  • 32. 32 Khai Khai báo báo kiểu kiểu của của 1 1 phần phần tử tử và và kiểu kiểu danh danh sách sách liên liên kết kết đơn và để đơn đơn và để đơn giản ta xét mỗi node gồm vùng chứa dữ liệu là kiểu số nguyên giản ta xét mỗi node gồm vùng chứa dữ liệu là kiểu số nguyên : : // kiểu của một phần tử trong danh sách typedef struct Node { int data; NODE * link; }NODE; typedef struct List // kiểu danh sách liên kết { NODE* first; NODE* last; }LIST; Trong thực tế biến data là một kiểu struct Tổ Tổ chức chức, , quản quản lý lý
  • 33. 33  Thủ Thủ tục tục GetNode để để tạo tạo ra ra một một phần phần tử tử cho cho danh danh sách sách với với thông thông tin tin chứa chứa trong trong x x NODE* GetNode(int x) { NODE *p; // Cấp phát vùng nhớ cho phần tử p = (NODE*)malloc(sizeof(NODE))//p= new NODE; if (p==NULL) { cout<<“Khong du bo nho!”; exit(1); } p->data = x; // Gán thông tin cho phần tử p p->link = NULL; return p; } Tạo Tạo một một phần phần tử tử
  • 34. 34 Để Để tạo tạo một một phần phần tử tử mới mới cho cho danh danh sách sách, , cần cần thực thực hiện hiện câu câu lệnh lệnh: : new_ele = GetNode(x);   new new_ _ele ele sẽ sẽ quản quản lý lý địa địa chỉ chỉ của của phần phần tử tử mới mới được được tạo tạo. . Tạo Tạo một một phần phần tử tử
  • 35. 35  Tạo Tạo danh danh sách sách rỗng rỗng  Thêm Thêm một một phần phần tử tử vào vào danh danh sách sách  Tìm Tìm kiếm kiếm một một giá giá trị trị trên trên danh danh sách sách  Trích Trích một một phần phần tử tử ra ra khỏi khỏi danh danh sách sách  Duyệt Duyệt danh danh sách sách  Hủy Hủy toàn toàn bộ bộ danh danh sách sách Các Các thao thao tác tác cơ cơ sở sở
  • 36. 36 void void Init Init( (LIST LIST &l) &l) { { l.first = l.last = NULL; l.first = l.last = NULL; } } Khởi Khởi tạo tạo danh danh sách sách rỗng rỗng first last
  • 37. 37 Có 3 vị trí thêm phần tử mới vào danh sách : Có 3 vị trí thêm phần tử mới vào danh sách :  Thêm Thêm vào vào đầu đầu danh danh sách sách  Nối Nối vào vào cuối cuối danh danh sách sách  Chèn Chèn vào vào danh danh sách sách sau sau một một phần phần tử tử q q Thêm Thêm một một phần phần tử tử
  • 39. 39 A B C D E first last Thêm Thêm một một phần phần tử tử vào vào đầu đầu X new_ele
  • 40. 40 //input: danh sách (first, last), phần tử mới new_ele //input: danh sách (first, last), phần tử mới new_ele //output: danh sách (first, last) với new_ele ở đầu DS //output: danh sách (first, last) với new_ele ở đầu DS  Nếu Nếu Danh sách rỗng Danh sách rỗng Thì Thì  first = new_ele; first = new_ele;  last = first; last = first;  Ngược lại Ngược lại  new_ele ->link = first; new_ele ->link = first;  first = new_ele ; first = new_ele ; Thêm Thêm một một phần phần tử tử vào vào đầu đầu
  • 41. 41 void AddFirst(LIST &l, NODE* new_ele) { if (l.first == NULL) //Xâu rỗng { l.first = new_ele; l.last = l.first; } else { new_ele->link = l.first; l.first = new_ele; } } Thêm Thêm một một phần phần tử tử vào vào đầu đầu
  • 42. 42 // //input input: : danh danh sách sách (first, (first, last last), ), thành thành phần phần dữ dữ liệu liệu X X // //output output: : danh danh sách sách (first, (first, last last) ) với với phần phần tử tử chứa chứa X X ở ở đầu đầu DS DS  Tạo Tạo phần phần tử tử mới mới new new_ _ele ele để để chứa chứa dữ dữ liệu liệu X X  Nếu Nếu tạo tạo được được: : Thêm Thêm new new_ _ele ele vào vào đầu đầu danh danh sách sách  Ngược Ngược lại lại Báo Báo lỗi lỗi Thêm Thêm một một thành thành phần phần dữ dữ liệu liệu vào vào đầu đầu
  • 43. 43 NODE* Insertfirst(LIST &l, int x) { NODE* new_ele = GetNode(x); if (new_ele == NULL) return NULL; AddFirst(l, new_ele); return new_ele; } Thêm Thêm một một thành thành phần phần dữ dữ liệu liệu vào vào đầu đầu
  • 44. 44 void void create_list_first create_list_first( (LIST LIST &l, &l, int int x) x) { { NODE NODE *p; *p; int n; int n; cout cout<<“Nhap so phan tu:”; <<“Nhap so phan tu:”; cin cin>>n; >>n; for for ( (int int i=1;i<=n;i++) i=1;i<=n;i++) // nen dung vong lap do while de viet // nen dung vong lap do while de viet { { // //Insertfirst Insertfirst(l,x); (l,x); p= p=GetNode GetNode(x); (x); AddFirst AddFirst(l,p); (l,p); } } } } Tạo Link list bằng cách thêm vào đầu Tạo Link list bằng cách thêm vào đầu
  • 45. 45 A B C D E first last Thêm Thêm một một phần phần tử tử vào vào cuối cuối X new_ele
  • 46. 46 // //input input: : danh danh sách sách (first, (first, last last), ), phần phần tử tử mới mới new new_ _ele ele // //output output: : danh danh sách sách (first, (first, last last) ) với với new new_ _ele ele ở ở cu cuố ối i DS DS  Nếu Nếu Danh sách rỗng Danh sách rỗng Thì Thì  first = new_ele; first = new_ele;  last = first; last = first;  Ngược lại Ngược lại  last->link = new_ele ; last->link = new_ele ;  last = new_ele ; last = new_ele ; Thêm Thêm một một phần phần tử tử vào vào cuối cuối
  • 47. 47 void InsertLast(LIST &l, NODE *new_ele) { if (l.first==NULL) { l.first = new_ele; l.last = l.first; } else { l.last->link = new_ele; l.last = new_ele ; } } Thêm Thêm một một phần phần tử tử vào vào cuối cuối
  • 48. 48 // //input input: : danh danh sách sách (first, (first, last last), ), thành thành phần phần dữ dữ liệu liệu X X // //output output: : danh danh sách sách (first, (first, last last) ) với với phần phần tử tử chứa chứa X X ở ở cuối cuối DS DS  Tạo Tạo phần phần tử tử mới mới new new_ _ele ele để để chứa chứa dữ dữ liệu liệu X X  Nếu Nếu tạo tạo được được: : Thêm Thêm new new_ _ele ele vào vào cuối cuối danh danh sách sách  Ngược Ngược lại lại Báo Báo lỗi lỗi Thêm Thêm một một thành thành phần phần dữ dữ liệu liệu vào vào cuối cuối
  • 49. 49 NODE* InputLast(LIST &l) { int x,n; printf(“Nhap so phan tu :”); scanf(“%d”,&n); for(int i=0;i<n;i++) { printf(“Nhap phan tu thu %d :”,i); scanf(“%d”,&x); NODE* p=GetNode(x); InsertLast(l, new_ele); } } Thêm Thêm một một thành thành phần phần dữ dữ liệu liệu vào vào cuối cuối
  • 50. 50 void void create_list_last create_list_last( (list list &l, &l, int int x) x) { { node node *p; *p; int n; int n; cout cout<<“Nhap so phan tu:”; <<“Nhap so phan tu:”; cin cin>>n; >>n; for for ( (int int i=1;i<=n;i++) i=1;i<=n;i++) // nen dung vong lap do while de viet // nen dung vong lap do while de viet { { p= p=GetNode GetNode(x); (x); InsertLast( InsertLast(l,p); l,p); } } } } Tạo Link list bằng cách thêm vào cuối Tạo Link list bằng cách thêm vào cuối
  • 51. 51 A B C D E first last Chèn Chèn một một phần phần tử tử sau sau q q X new_ele q
  • 52. 52 // //input input: : danh danh sách sách (first, (first, last last), ), q q, , phần phần tử tử mới mới new new_ _ele ele // //output output: : danh danh sách sách (first, (first, last last) ) với với new new_ _ele ele ở ở sau sau q q Nếu Nếu ( ( q q != != NULL NULL) ) thì thì new new_ _ele ele -> link = -> link = q q -> link; -> link; q q -> link = -> link = new new_ _ele ele ; ; Nếu Nếu ( ( q q ==last) ==last) thì thì last last = = new new_ _ele ele; ; Ngược Ngược lại lại Thêm Thêm new new_ _ele ele vào vào đầu đầu danh danh sách sách Chèn Chèn một một phần phần tử tử sau sau q q
  • 53. 53 void InsertAfter(LIST &l,NODE *q, NODE* new_ele) { if (q!=NULL && new_ele !=NULL) { new_ele->link = q->link; q->link = new_ele; if(q == l.last) l.last = new_ele; } } Chèn Chèn một một phần phần tử tử sau sau q q
  • 54. 54  Duyệt Duyệt danh danh sách sách là là thao thao tác tác thường thường được được thực thực hiện hiện khi khi có có nhu nhu cầu cầu xử xử lý lý các các phần phần tử tử của của danh danh sách sách theo theo cùng cùng một một cách cách thức thức hoặc hoặc khi khi cần cần lấy lấy thông thông tin tin tổng tổng hợp hợp từ từ các các phần phần tử tử của của danh danh sách sách như như: :  Đếm Đếm các các phần phần tử tử của của danh danh sách sách, ,  Tìm Tìm tất tất cả cả các các phần phần tử tử thoả thoả điều điều kiện kiện, ,  Hủy Hủy toàn toàn bộ bộ danh danh sách sách ( (và và giải giải phóng phóng bộ bộ nhớ nhớ) ) Duyệt Duyệt danh danh sách sách
  • 55. 55  Bước 1: p = first; Bước 1: p = first; //Cho p trỏ đến phần tử đầu danh sách //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 Bước 2: Trong khi (Danh sách chưa hết) thực hiện  B21 : Xử lý phần tử p; B21 : Xử lý phần tử p;  B22 : p:=p->link; B22 : p:=p->link; // Cho p trỏ tới phần tử kế // Cho p trỏ tới phần tử kế void ProcessList (LIST &l) { NODE *p; p = l.first; while (p!= NULL){ ProcessNode(p); // xử lý cụ thể tùy ứng dụng p = p->link; } } Duyệt Duyệt danh danh sách sách
  • 56. 56 DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 first p
  • 57. 57 p =first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 3000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 58. 58 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 3000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 59. 59 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 3000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 60. 60 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 5000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 61. 61 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 5000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 62. 62 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 5000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 63. 63 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 4000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 64. 64 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 4000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 65. 65 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 4000 first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 66. 66 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 NULL first p DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 67. 67 p = first; while (p!=NULL) { printf printf(“%dt”,p->data); (“%dt”,p->data); p = p->link; } 3000 “Tran Tran” 5000 “Ngoc Ngoc” 4000 “Thao Thao” NULL 3000 5000 4000 NULL first p K t thúc ế DSLK – Minh họa in danh sách DSLK – Minh họa in danh sách
  • 68. 68 In các phần tử trong danh sách In các phần tử trong danh sách void void Output Output( (LIST LIST l) l) { { NODE* NODE* p=l.first; p=l.first; while while(p!= (p!=NULL NULL) ) { { cout<<p->data<<“t”; cout<<p->data<<“t”; p=p ->link; p=p ->link; } } cout<<endl; cout<<endl; } }
  • 69. 69 Tìm kiếm một phần tử có khóa x Tìm kiếm một phần tử có khóa x NODE* NODE* Search Search( (LIST LIST l , int x) l , int x) { { NODE* NODE* p=l.first; p=l.first; while while( p!= ( p!=NULL NULL && p->data!=x) && p->data!=x) p=p->link; p=p->link; return return p; p; } }
  • 70. 70 Xóa một node của danh sách Xóa một node của danh sách Xóa node đầu của danh sách Xóa node đầu của danh sách Để xóa node đầu danh sách l (khác rỗng) Để xóa node đầu danh sách l (khác rỗng)  Gọi p là node đầu của danh sách (là l.first) Gọi p là node đầu của danh sách (là l.first)  Cho l.first trỏ vào node sau node p (là p->link) Cho l.first trỏ vào node sau node p (là p->link)  Nếu danh sách trở tahnh2 rỗng thì l.last=NULL Nếu danh sách trở tahnh2 rỗng thì l.last=NULL  Giải phóng vùng nhớ mà p trỏ tới Giải phóng vùng nhớ mà p trỏ tới
  • 71. 71 Xóa một node của danh sách Xóa một node của danh sách A B C D E first last p
  • 72. 72 void void RemoveFirst RemoveFirst( (LIST LIST &l) &l) { { if if(l.first != (l.first != NULL NULL) ) { { NODE* NODE* p=l.first; p=l.first; l.first=p->link; l.first=p->link; if if(l.first == (l.first == NULL NULL) l.last= ) l.last=NULL NULL;//Nếu danh sách rỗng ;//Nếu danh sách rỗng free free(p); (p); } } } } Xóa một node của danh sách Xóa một node của danh sách
  • 73. 73 Xóa node sau node q trong danh sách Xóa node sau node q trong danh sách Điều kiện để có thể xóa được node sau q là : Điều kiện để có thể xóa được node sau q là :  q phải khác NULL q phải khác NULL  Node sau q phải khác NULL Node sau q phải khác NULL Có 3 thao tác Có 3 thao tác  Gọi p là node sau q Gọi p là node sau q  Cho vùng link của q trỏ vào node đứng sau p (là l.link) Cho vùng link của q trỏ vào node đứng sau p (là l.link)  Nếu p là phần tử cuối thì l.last trỏ vào q Nếu p là phần tử cuối thì l.last trỏ vào q  Giải phóng vùng nhớ mà p trỏ tới Giải phóng vùng nhớ mà p trỏ tới Xóa một node của danh sách Xóa một node của danh sách
  • 74. 74 Xóa node sau node q trong danh sách Xóa node sau node q trong danh sách A B C D E first last q p
  • 75. 75 void void RemoveAfter RemoveAfter( (LIST LIST &l, &l, NODE NODE *q ) *q ) { { if if(q != (q !=NULL NULL && q->link != && q->link !=NULL NULL) ) { { NODE NODE* p = q->link; * p = q->link; q->link = p->link; q->link = p->link; if if(p==l.last) (p==l.last) l.last=q; l.last=q; free free(p); (p); } } } } Xóa node sau node q trong danh sách Xóa node sau node q trong danh sách
  • 76. 76  Để Để h hủ ủy y toàn toàn bộ bộ danh danh sách sách, , thao thao tác tác xử xử lý lý bao bao gồm gồm hành hành động động giải giải phóng phóng một một phần phần tử tử, , do do vậy vậy phải phải cập cập nhật nhật các các liên liên kết kết liên liên quan quan: :  Bước Bước 1: 1: Trong Trong khi khi ( (Danh Danh sách sách chưa chưa hết hết) ) thực thực hiện hiện  B B11: 11:  p p = first; = first;  first =first->link; first =first->link; // // Cho Cho p p trỏ trỏ tới tới phần phần tử tử kế kế  B B12: 12:  Hủy Hủy p p; ;  Bước Bước 2: 2:  last = last = NULL NULL; ;// //Bảo Bảo đảm đảm tính tính nhất nhất quán quán khi khi xâu xâu rỗng rỗng Hủy Hủy toàn toàn bộ bộ danh danh sách sách
  • 77. 77 void RemoveList(LIST &l) { NODE *p; while (l.first!= NULL) { p = l.first; l.first = p->link; free( p); } l.last = NULL; } Hủy Hủy toàn toàn bộ bộ danh danh sách sách
  • 78. Sắp Sắp xếp trên xếp trên danh danh sách sách liên kết đơn liên kết đơn
  • 79. 79 Sắp Sắp xếp xếp danh danh sách sách Cách Cách tiếp tiếp cận cận: :  Phương án 1: Phương án 1: Hoán vị nội dung các phần tử trong danh sách Hoán vị nội dung các phần tử trong danh sách (thao tác trên vùng data). (thao tác trên vùng data).  Phương án 2 : Phương án 2 : Thay đổi các mối liên kết (thao tác trên vùng Thay đổi các mối liên kết (thao tác trên vùng link) link)
  • 80. 80 Sắp Sắp xếp xếp danh danh sách sách Hoán Hoán vị vị nội nội dung dung các các phần phần tử tử trong trong danh danh sách sách  Cài Cài đặt đặt lại lại trên trên danh sách liên kết danh sách liên kết một một trong trong những những thuật thuật toán toán sắp sắp xếp xếp đã đã biết biết trên trên mảng mảng  Điểm Điểm khác khác biệt biệt duy duy nhất nhất là là cách cách thức thức truy truy xuất xuất đến đến các các phần phần tử tử trên trên danh sách liên kết danh sách liên kết thông thông qua qua liên liên kết kết thay thay vì vì chỉ chỉ số số như như trên trên mảng mảng. .  Do Do thực thực hiện hiện hoán hoán vị vị nội nội dung dung của của các các phần phần tử tử nên nên đòi đòi hỏi hỏi sử sử dụng dụng thêm thêm vùng vùng nhớ nhớ trung trung gian gian   chỉ chỉ thích thích hợp hợp với với các các xâu xâu có có các các phần phần tử tử có có thành thành phần phần data data kích kích thước thước nhỏ nhỏ. .  Khi Khi kích kích thước thước của của trường trường data data lớn lớn, , việc việc hoán hoán vị vị giá giá trị trị của của hai hai phân phân tử tử sẽ sẽ chiếm chiếm chi chi phí phí đáng đáng kể kể. .
  • 81. 81 void void SLL_InterChangeSort SLL_InterChangeSort ( ( List List &l ) &l ) { { for for ( ( Node Node* p=l.first ; p!= * p=l.first ; p!=l.last l.last ; p=p->link ) ; p=p->link ) for for ( ( Node Node* q=p->link ; q!= * q=p->link ; q!=NULL NULL ; q=q->link ) ; q=q->link ) if if ( p->data > q->data ) ( p->data > q->data ) Swap Swap( p->data , q->data ); ( p->data , q->data ); } } Sắp xếp bằng phương pháp đổi chổ trực tiếp ( Interchange Sort )
  • 82. 82 12 2 8 1 5 p q l.first l.last Sắp xếp đổi chổ trực tiếp ( Interchange Sort )
  • 83. 83 1 12 8 2 5 p q l.first l.last Sắp xếp đổi chổ trực tiếp ( Interchange Sort )
  • 84. 84 1 2 12 8 5 p q l.first l.last Sắp xếp đổi chổ trực tiếp ( Interchange Sort )
  • 85. 85 1 2 5 12 8 p q l.first l.last Sắp xếp đổi chổ trực tiếp ( Interchange Sort )
  • 86. 86 1 2 5 8 12 p q Dừng l.first l.last Sắp xếp đổi chổ trực tiếp ( Interchange Sort )
  • 87. 87 Sắp xếp bằng phương pháp chọn trực tiếp Sắp xếp bằng phương pháp chọn trực tiếp ( ( Selection sort Selection sort ) ) void ListSelectionSort (LIST &l) { for ( Node* p = l.first ; p != l.last ; p = p->link ) { Node* min = p; for ( Node* q = p->link ; q != NULL ; q = q->link ) if ( min->data > q->data ) min = q ; Swap(min->data, p->data); } }
  • 88. 88 12 2 8 1 5 p min l.first l.last Sắp xếp bằng phương pháp chọn trực tiếp Sắp xếp bằng phương pháp chọn trực tiếp ( ( Selection sort Selection sort ) )
  • 89. 89 1 2 8 12 5 p min l.first l.last Sắp xếp bằng phương pháp chọn trực tiếp Sắp xếp bằng phương pháp chọn trực tiếp ( ( Selection sort Selection sort ) )
  • 90. 90 1 2 8 12 5 p min l.first l.last Sắp xếp bằng phương pháp chọn trực tiếp Sắp xếp bằng phương pháp chọn trực tiếp ( ( Selection sort Selection sort ) )
  • 91. 91 1 2 5 12 8 p min l.first l.last Sắp xếp bằng phương pháp chọn trực tiếp Sắp xếp bằng phương pháp chọn trực tiếp ( ( Selection sort Selection sort ) )
  • 92. 92 1 2 5 8 12 p min l.first l.last Dừng Sắp xếp bằng phương pháp chọn trực tiếp Sắp xếp bằng phương pháp chọn trực tiếp ( ( Selection sort Selection sort ) )
  • 93. 93 void void SLL_BubleSort SLL_BubleSort ( ( List List l ) l ) { { Node Node* t = * t = l.last l.last ; ; for for ( ( Node Node* p = * p = l.first l.first ; p != ; p != NULL NULL ; p = p->link) ; p = p->link) { { Node Node* t1; * t1; for for ( ( Node Node* q= * q=l.first l.first ; p!=t ; q=q->link ) ; p!=t ; q=q->link ) { { if if( q->data ( q->data > > q->link->data ) q->link->data ) Swap Swap( q->data ( q->data , , q->link->data ); q->link->data ); t1 = q ; t1 = q ; } } t = t1; t = t1; } } } } Sắp xếp bằng phương pháp nổi bọt Sắp xếp bằng phương pháp nổi bọt ( ( Bubble Bubble sort sort ) )
  • 94. 94 12 2 8 1 5 q q->link l.first l.last Sắp xếp bằng phương pháp nổi bọt Sắp xếp bằng phương pháp nổi bọt ( ( Bubble sort Bubble sort ) )
  • 95. 95 2 8 1 5 12 q q->link l.first l.last Sắp xếp bằng phương pháp nổi bọt Sắp xếp bằng phương pháp nổi bọt ( ( Bubble sort Bubble sort ) )
  • 96. 96 2 1 5 8 12 q q->link l.first l.last Sắp xếp bằng phương pháp nổi bọt Sắp xếp bằng phương pháp nổi bọt ( ( Bubble sort Bubble sort ) )
  • 97. 97 1 2 5 8 12 q q->link l.first l.last Sắp xếp bằng phương pháp nổi bọt Sắp xếp bằng phương pháp nổi bọt ( ( Bubble sort Bubble sort ) )
  • 98. 98 1 2 5 8 12 l.first l.last Dừng Sắp xếp bằng phương pháp nổi bọt Sắp xếp bằng phương pháp nổi bọt ( ( Bubble sort Bubble sort ) )
  • 99. 99 Sắp Sắp xếp xếp Thay Thay đổi đổi các các mối mối liên liên kết kết  Thay vì hoán đổi giá trị, ta sẽ tìm cách thay đổi trình tự móc Thay vì hoán đổi giá trị, ta sẽ tìm cách thay đổi trình tự móc nối của các phần tử sao cho tạo lập nên được thứ tự mong nối của các phần tử sao cho tạo lập nên được thứ tự mong muốn muốn   chỉ thao tác trên các móc nối (link). chỉ thao tác trên các móc nối (link).  Kích thước của trường link: Kích thước của trường link:  Không phụ thuộc vào bản chất dữ liệu lưu trong xâu Không phụ thuộc vào bản chất dữ liệu lưu trong xâu  Bằng kích thước 1 con trỏ (2 hoặc 4 byte trong môi Bằng kích thước 1 con trỏ (2 hoặc 4 byte trong môi trường 16 bit, 4 hoặc 8 byte trong môi trường 32 bit…) trường 16 bit, 4 hoặc 8 byte trong môi trường 32 bit…)  Thao tác trên các móc nối thường phức tạp hơn thao tác trực Thao tác trên các móc nối thường phức tạp hơn thao tác trực tiếp trên dữ liệu. tiếp trên dữ liệu.  Cần cân nhắc khi chọn cách tiếp cận: Nếu dữ liệu không quá Cần cân nhắc khi chọn cách tiếp cận: Nếu dữ liệu không quá lớn thì nên chọn phương án 1 hoặc một thuật toán hiệu quả lớn thì nên chọn phương án 1 hoặc một thuật toán hiệu quả nào đó. nào đó.
  • 100. 100 Phương pháp lấy Phương pháp lấy Node Node ra khỏi danh ra khỏi danh sách giữ nguyên địa chỉ của sách giữ nguyên địa chỉ của Node Node 12 2 5 1 q 8 p 1 . q->link = p->link ; // p->link chứa địa chỉ sau p 2 . q->link = NULL ; // p không liên kết phần tử Node
  • 101. 101 Quick Sort : Thuật toán Quick Sort : Thuật toán //input: xâu (first, last) //input: xâu (first, last) //output: xâu đã được sắp tăng dần //output: xâu đã được sắp tăng dần  Bước 1: Nếu xâu có ít hơn 2 phần tử Bước 1: Nếu xâu có ít hơn 2 phần tử Dừng; Dừng; //xâu đã có thứ tự //xâu đã có thứ tự  Bước 2: Chọn X là phần tử đầu xâu L làm ngưỡng. Trích X ra Bước 2: Chọn X là phần tử đầu xâu L làm ngưỡng. Trích X ra khỏi L. khỏi L.  Bước 3: Tách xâu L ra làm 2 xâu L Bước 3: Tách xâu L ra làm 2 xâu L1 1 (gồm các phần tử nhỏ hơn (gồm các phần tử nhỏ hơn hay bằng X) và L hay bằng X) và L2 2 (gồm các phần tử lớn hơn X). (gồm các phần tử lớn hơn X).  Bước 4: Sắp xếp Bước 4: Sắp xếp Quick Sort Quick Sort (L (L1 1). ).  Bước 5: Sắp xếp Bước 5: Sắp xếp Quick Sort Quick Sort (L (L2 2). ).  Bước 6: Nối L Bước 6: Nối L1 1, X, và L , X, và L2 2 lại theo trình tự ta có xâu L đã được lại theo trình tự ta có xâu L đã được sắp xếp. sắp xếp.
  • 102. 102 Sắp Sắp xếp xếp quick quick sort sort first 6 8 2 4 5 1
  • 103. 103 Quick Quick sort sort : : phân phân hoạch hoạch first 6 8 2 4 5 1 X Chọn phần tử đầu xâu làm ngưỡng
  • 104. 104 Quick Quick sort sort : : phân phân hoạch hoạch first 6 8 2 4 5 1 X Tách xâu hiện hành thành 2 xâu first1 first2
  • 105. 105 Quick Quick sort sort : : phân phân hoạch hoạch first 6 8 2 4 5 1 X Tách xâu hiện hành thành 2 xâu first1 first2
  • 106. 106 Quick Quick sort sort : : phân phân hoạch hoạch first 6 8 2 4 5 1 X Tách xâu hiện hành thành 2 xâu first1 first2
  • 107. 107 Quick Quick sort sort : : phân phân hoạch hoạch first 6 8 2 4 5 1 X Tách xâu hiện hành thành 2 xâu first1 first2
  • 109. 109 Quick Quick sort sort first 6 8 2 4 5 1 X Nối l1, X, l2 first1 first2 Đưa kết quả vào first
  • 110. 110 void SListAppend(SLIST &l, LIST &l2) { if (l2.first == NULL) return; if (l.first == NULL) l = l2; else { l.first->link = l2.first; l.last = l2.last; } Init(l2); } Nối 2 danh sách Nối 2 danh sách
  • 111. 111 void SListQSort(SLIST &l) { NODE *X, *p; SLIST l1, l2; if (list.first == list.last) return; Init(l1); Init(l2); X = l.first; l.first=x->link; while (l.first != NULL) { p = l.first; if (p->data <= X->data) AddFirst(l1, p); else AddFirst(l2, p); } SListQSort(l1); SListQSort(l2); SListAppend(l, l1); AddFirst(l, X); SListAppend(l, l2); }
  • 112. 112  Nhận Nhận xét xét: :  Quick Quick sort sort trên trên xâu xâu đơn đơn đơn đơn giản giản hơn hơn phiên phiên bản bản của của nó nó trên trên mảng mảng một một chiều chiều  Khi Khi dùng dùng quick quick sort sort sắp sắp xếp xếp một một xâu xâu đơn đơn, , chỉ chỉ có có một một chọn chọn lựa lựa phần phần tử tử cầm cầm canh canh duy duy nhất nhất hợp hợp lý lý là là phần phần tử tử đầu đầu xâu xâu. . Chọn Chọn bất bất kỳ kỳ phần phần tử tử nào nào khác khác cũng cũng làm làm tăng tăng chi chi phí phí một một cách cách không không cần cần thiết thiết do do cấu cấu trúc trúc tự tự nhiên nhiên của của xâu xâu. . Quick Quick sort sort : : nhận nhận xét xét
  • 113. Danh Danh sách hạn chế sách hạn chế Stack ( Ngăn xếp ) Stack ( Ngăn xếp ) Queue Queue ( ( Hàng Hàng đợi đợi ) )
  • 115. 115 Stack Stack  Stack Stack là là một một vật vật chứa chứa ( (container container) ) các các đối đối tượng tượng làm làm việc việc theo theo cơ cơ chế chế LIFO LIFO ( (Last Last In In First First Out Out) )   Việc Việc thêm thêm một một đối đối tượng tượng vào vào stack stack hoặc hoặc lấy lấy một một đối đối tượng tượng ra ra khỏi khỏi stack stack được được thực thực hiện hiện theo theo cơ cơ chế chế “ “Vào sau ra Vào sau ra trước” trước”. .  Các Các đối đối tượng tượng có có thể thể được được thêm thêm vào vào stack stack bất bất kỳ kỳ lúc lúc nào nào nhưng nhưng chỉ chỉ có có đối đối tượng tượng thêm thêm vào vào sau sau cùng cùng mới mới được được phép phép lấy lấy ra ra khỏi khỏi stack stack. .  “ “Push” Push”: : Thao Thao tác tác thêm thêm 1 1 đối đối tượng tượng vào vào stack stack  “ “Pop” Pop”: : Thao Thao tác tác lấy lấy 1 1 đối đối tượng tượng ra ra khỏi khỏi stack stack. .  Stack Stack có có nhiều nhiều ứng ứng dụng dụng: : khử khử đệ đệ qui qui, , tổ tổ chức chức lưu lưu vết vết các các quá quá trình trình tìm tìm kiếm kiếm theo theo chiều chiều sâu sâu và và quay quay lui lui, , vét vét cạn cạn, , ứng ứng dụng dụng trong trong các các bài bài toán toán tính tính toán toán biểu biểu thức thức, , … …
  • 116. 116 Gi Giới thiệu ới thiệu  LIFO: Last In First Out LIFO: Last In First Out  Thao tác Pop, Push chỉ diễn ra ở 1 đầu Thao tác Pop, Push chỉ diễn ra ở 1 đầu
  • 117. 117 Hi Hiện thực stack ện thực stack ( (Implementation of a Stack Implementation of a Stack ) ) Mảng 1 chiều Danh sách LK Kích thước stack khi quá thiếu, lúc quá thừa Cấp phát động! Push / Pop hơi phức tạp Push/Pop khá dễ dàng
  • 118. 118 Stack ( Ngăn xếp ) Stack ( Ngăn xếp )  Stack Stack là là một một CTDL CTDL trừu trừu tượng tượng tuyến tuyến tính tính hỗ hỗ trợ trợ 2 2 thao thao tác tác chính chính: :  Push Push( (o o): ): Thêm Thêm đối đối tượng tượng o o vào vào đầu đầu stack stack  Pop Pop(): ():Lấy Lấy đối đối tượng tượng ở ở đầu đầu stack stack ra ra khỏi khỏi stack stack và và trả trả về về giá giá trị trị của của nó nó. . Nếu Nếu stack stack rỗng rỗng thì thì lỗi lỗi sẽ sẽ xảy xảy ra ra. .  Stack Stack cũng cũng hỗ hỗ trợ trợ một một số số thao thao tác tác khác khác: :  isEmpty isEmpty(): (): Kiểm Kiểm tra tra xem xem stack stack có có rỗng rỗng không không. .  Top Top(): (): Trả Trả về về giá giá trị trị của của phần phần tử tử nằm nằm ở ở đầu đầu stack stack mà mà không không hủy hủy nó nó khỏi khỏi stack stack. . Nếu Nếu stack stack rỗng rỗng thì thì lỗi lỗi sẽ sẽ xảy xảy ra ra. .
  • 119. 119 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng ( (Array Implementation of a Stack) Array Implementation of a Stack)  Có Có thể thể tạo tạo một một stack stack bằng bằng cách cách khai khai báo báo một một mảng mảng 1 1 chiều chiều với với kích kích thước thước tối tối đa đa là là N N ( (ví ví dụ dụ: : N N =1000). =1000).  Stack Stack có có thể thể chứa chứa tối tối đa đa N N phần phần tử tử đánh đánh số số từ từ 0 0 đến đến N N-1. -1.  Phần Phần tử tử nằm nằm ở ở đầu đầu stack stack sẽ sẽ có có chỉ chỉ số số t t ( (lúc lúc đó đó trong trong stack stack đang đang chứa chứa t t+1 +1 phần phần tử tử) )  Để Để khai khai báo báo một một stack stack, , ta ta cần cần một một mảng mảng 1 1 chiều chiều S S, , biến biến nguyên nguyên t t cho cho biết biết chỉ chỉ số số của của đầu đầu stack stack và và hằng hằng số số N N cho cho biết biết kích kích thước thước tối tối đa đa của của stack stack. . Data S [N]; int t;
  • 120. 120 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng  Lệnh Lệnh top top = 0 = 0 sẽ sẽ tạo tạo ra ra một một stack stack S S rỗng rỗng. .  Giá Giá trị trị của của t t sẽ sẽ cho cho biết biết số số phần phần tử tử hiện hiện hành hành có có trong trong stack stack. .  Khi Khi cài cài đặt đặt bằng bằng mảng mảng 1 1 chiều chiều, , stack stack có có kích kích thước thước tối tối đa đa nên nên cần cần xây xây dựng dựng thêm thêm một một thao thao tác tác phụ phụ cho cho stack stack: :  Full Full(): (): Kiểm Kiểm tra tra xem xem stack stack có có đầy đầy chưa chưa. .  Khi Khi stack stack đầy đầy, , việc việc gọi gọi đến đến hàm hàm push push() () sẽ sẽ phát phát sinh sinh ra ra lỗi lỗi. .
  • 121. 121 Khai báo stack Khai báo stack typedef struct typedef struct node node { { int int data; data; }; }; typedef struct typedef struct stack stack { { int int top; top; node node list[N]; list[N]; }; };
  • 122. 122  Khởi tạo Stack: Khởi tạo Stack: void void Init Init( (stack stack &s) &s) { { s.top=0; s.top=0; } } Biểu diễn Stack dùng mảng Biểu diễn Stack dùng mảng
  • 123. 123 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng  Kiểm Kiểm tra tra stack stack rỗng rỗng hay hay không không int Empty(stack s) { if(s.top==0) return 1; return 0; }
  • 124. 124 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng  Kiểm Kiểm tra tra stack stack đầy đầy hay hay không không int Full(stack s) { if(s.top==N-1) return 1; return 0; }
  • 125. 125 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng  Thêm Thêm một một phần phần tử tử x x vào vào stack stack S S void Push(stack &s,node x) { if(!Full(s)) // stack chưa đầy s.list[++s.top]=x; }
  • 126. 126 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng  Trích Trích thông thông tin tin và và huỷ huỷ phần phần tử tử ở ở đỉnh đỉnh stack stack S S node Pop(stack &s) { node n; if(!Empty(s)) // stack khác r?ng { n=s.list[s.top]; s.top--; } return n; }
  • 127. 127 Biểu Biểu diễn diễn Stack Stack dùng dùng mảng mảng  Nhận Nhận xét xét: :  Các Các thao thao tác tác trên trên đều đều làm làm việc việc với với chi chi phí phí O O(1). (1).  Việc Việc cài cài đặt đặt stack stack thông thông qua qua mảng mảng một một chiều chiều đơn đơn giản giản và và khá khá hiệu hiệu quả quả. .  Tuy Tuy nhiên nhiên, , hạn hạn chế chế lớn lớn nhất nhất của của phương phương án án cài cài đặt đặt này này là là giới giới hạn hạn về về kích kích thước thước của của stack stack N N. . Giá Giá trị trị của của N N có có thể thể quá quá nhỏ nhỏ so so với với nhu nhu cầu cầu thực thực tế tế hoặc hoặc quá quá lớn lớn sẽ sẽ làm làm lãng lãng phí phí bộ bộ nhớ nhớ. .
  • 128. 128 Biểu Biểu diễn diễn Stack Stack dùng dùng danh danh sách sách liên liên kết kết ( (Implementation of a Stack Using Linked Implementation of a Stack Using Linked Representation) Representation)  Có Có thể thể tạo tạo một một stack stack bằng bằng cách cách sử sử dụng dụng một một danh danh sách sách liên liên kết kết đơn đơn ( (DSLK DSLK). ).  DSLK DSLK có có những những đặc đặc tính tính rất rất phù phù hợp hợp để để dùng dùng làm làm stack stack vì vì mọi mọi thao thao tác tác trên trên stack stack đều đều diễn diễn ra ra ở ở đầu đầu stack stack. . stack stack *s;
  • 129. 129 Khai báo stack Khai báo stack typedef struct typedef struct node node { { int int data; data; node *link; node *link; }; }; typedef struct typedef struct stack stack { { node node *top; *top; }; };
  • 130. 130 Biểu Biểu diễn diễn Stack Stack dùng dùng danh danh sách sách liên liên kết kết  Khôûi taïo stack Khôûi taïo stack void void Init Init( (stack stack &t) &t) { { t.top=NULL; t.top=NULL; } }
  • 131. 131 Biểu Biểu diễn diễn Stack Stack dùng dùng danh danh sách sách liên liên kết kết  Kiểm Kiểm tra tra stack stack rỗng rỗng : : int Empty(stack t) { return t.top == NULL ? 1 : 0; // stack rỗng }
  • 132. 132  Thêm Thêm một một phần phần tử tử x x vào vào stack stack S S void void Push Push(stack &t, int x){ (stack &t, int x){ node node *p= *p=new new node; node; if if(p!=NULL){ (p!=NULL){ p->data=x; p->data=x; p->link=NULL; p->link=NULL; if if( (Empty Empty(t)) (t)) t.top=p; t.top=p; else else{ { p->link=t.top; p->link=t.top; t.top=p; t.top=p; } } } } } }
  • 133. 133 •Trích thông tin và huỷ phần tử ở đỉnh stack S Trích thông tin và huỷ phần tử ở đỉnh stack S int int Pop Pop(stack &t) (stack &t) { { node node *p; *p; int x; int x; if if(! (!Empty Empty(t)) (t)) { { p=t.top; p=t.top; t.top=p->link; t.top=p->link; x=p->data; x=p->data; free(p); free(p); return return x; x; } } } }
  • 134. 134 Ứng Ứng dụng dụng của của Stack Stack  Stack Stack thích thích hợp hợp lưu lưu trữ trữ các các loại loại dữ dữ liệu liệu mà mà trình trình tự tự truy truy xuất xuất ngược ngược với với trình trình tự tự lưu lưu trữ trữ  Một Một số số ứng ứng dụng dụng của của Stack Stack: :  Trong Trong trình trình biên biên dịch dịch ( (thông thông dịch dịch), ), khi khi thực thực hiện hiện các các thủ thủ tục tục, , Stack Stack được được sử sử dụng dụng để để lưu lưu môi môi trường trường của của các các thủ thủ tục tục. .  Lưu Lưu dữ dữ liệu liệu khi khi giải giải một một số số bài bài toán toán của của lý lý thuyết thuyết đồ đồ thị thị ( (như như tìm tìm đường đường đi đi) )  Khử Khử đệ đệ qui qui  ... ...
  • 135. 135 Ứng Ứng dụng dụng của của Stack Stack Ví Ví du du: :ï ï thủ thủ tục tục Quick Quick_ _Sort Sort dùng dùng Stack Stack để để khử khử đệ đệ qui qui: :  1. 1. l l:=1; :=1; r r:= :=n n; ;  2. 2. Chọn Chọn phần phần tử tử giữa giữa x x:= :=a a[( [(l l+ +r r) ) div div 2]; 2];  3. 3. Phân Phân hoạch hoạch ( (l l, ,r r) ) thành thành ( (l l1, 1,r r1) 1) và và ( (l l2, 2,r r2) 2) bằng bằng cách cách xét xét: :  y y thuộc thuộc ( (l l1, 1,r r1) 1) nếu nếu y y x x; ;  y y thuộc thuộc ( (l l2, 2,r r2) 2) ngược ngược lại lại; ;  4. 4. Nếu Nếu phân phân hoạch hoạch ( (l l2, 2,r r2) 2) có có nhiều nhiều hơn hơn 1 1 phần phần tử tử thực thực hiện hiện: :  Cất Cất ( (l l2, 2,r r2) 2) vào vào Stack Stack; ;  Nếu Nếu ( (l l1, 1,r r1) 1) có có nhiều nhiều hơn hơn 1 1 phần phần tử tử thực thực hiện hiện: :  l l= =l l1; 1;  r r= =r r1; 1;  Goto Goto 2; 2;  Ngược Ngược lại lại  Lấy Lấy ( (l l, ,r r) ) ra ra khỏi khỏi Stack Stack nếu nếu Stack Stack khác khác rỗng rỗng và và Goto Goto 2; 2;  Nếu Nếu không không dừng dừng; ;
  • 136. Hàng Hàng đợi đợi ( ( Queue Queue) )
  • 137. 137 Hàng Hàng đợi đợi ( ( Queue Queue) )  Hàng Hàng đợi đợi là là một một vật vật chứa chứa ( (container container) ) các các đối đối tượng tượng làm làm việc việc theo theo cơ cơ chế chế FIFO FIFO ( (First First In In First First Out Out) )   việc việc thêm thêm một một đối đối tượng tượng vào vào hàng hàng đợi đợi hoặc hoặc lấy lấy một một đối đối tượng tượng ra ra khỏi khỏi hàng hàng đợi đợi được được thực thực hiện hiện theo theo cơ cơ chế chế “Vào “Vào trước trước ra ra trước” trước”. .  Các Các đối đối tượng tượng có có thể thể được được thêm thêm vào vào hàng hàng đợi đợi bất bất kỳ kỳ lúc lúc nào nào nhưng nhưng chỉ chỉ có có đối đối tượng tượng thêm thêm vào vào đầu đầu tiên tiên mới mới được được phép phép lấy lấy ra ra khỏi khỏi hàng hàng đợi đợi. .
  • 139. 139 Giới thiệu Giới thiệu  FIFO FIFO  Thêm vào cuối và lấy ra ở đầu Thêm vào cuối và lấy ra ở đầu  Trong Trong tin tin học học, , CTDL CTDL hàng hàng đợi đợi có có nhiều nhiều ứng ứng dụng dụng: : khử khử đệ đệ qui qui, , tổ tổ chức chức lưu lưu vết vết các các quá quá trình trình tìm tìm kiếm kiếm theo theo chiều chiều rộng rộng và và quay quay lui lui, , vét vét cạn cạn, , tổ tổ chức chức quản quản lý lý và và phân phân phối phối tiến tiến trình trình trong trong các các hệ hệ điều điều hành hành, , tổ tổ chức chức bộ bộ đệm đệm bàn bàn phím phím, , … …
  • 140. 140 Hàng Hàng đợi đợi ( ( Queue Queue) )  Hàng Hàng đợi đợi hỗ hỗ trợ trợ các các thao thao tác tác: :  EnQueue( (o o): ):Thêm Thêm đối đối tượng tượng o o vào vào cuối cuối hàng hàng đợi đợi  DeQueue(): (): Lấy Lấy đối đối tượng tượng ở ở đầu đầu queue queue ra ra khỏi khỏi hàng hàng đợi đợi và và trả trả về về giá giá trị trị của của nó nó. . Nếu Nếu hàng hàng đợi đợi rỗng rỗng thì thì lỗi lỗi sẽ sẽ xảy xảy ra ra. .  Empty(): (): Kiểm Kiểm tra tra xem xem hàng hàng đợi đợi có có rỗng rỗng không không. .  Front(): (): Trả Trả về về giá giá trị trị của của phần phần tử tử nằm nằm ở ở đầu đầu hàng hàng đợi đợi mà mà không không hủy hủy nó nó. . Nếu Nếu hàng hàng đợi đợi rỗng rỗng thì thì lỗi lỗi sẽ sẽ xảy xảy ra ra. .
  • 141. 141 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Có Có thể thể tạo tạo một một hàng hàng đợi đợi bằng bằng cách cách sử sử dụng dụng một một mảng mảng 1 1 chiều chiều với với kích kích thước thước tối tối đa đa là là N N ( (ví ví dụ dụ, , N N=1000) =1000) theo theo kiểu kiểu xoay xoay vòng vòng ( (coi coi phần phần tử tử an an-1 -1 kề kề với với phần phần tử tử a a0 0) )   Hàng Hàng đợi đợi chứa chứa tối tối đa đa N N phần phần tử tử. .  Phần Phần tử tử ở ở đầu đầu hàng hàng đợi đợi ( (front front element element) ) sẽ sẽ có có chỉ chỉ số số f f. .  Phần Phần tử tử ở ở cuối cuối hàng hàng đợi đợi ( (rear rear element element) ) sẽ sẽ có có chỉ chỉ số số r r . .
  • 142. 142  Dùng một array: Có xu hướng dời về cuối array Dùng một array: Có xu hướng dời về cuối array  Hai cách hiện thực đầu tiên: Hai cách hiện thực đầu tiên:  Khi lấy một phần tử ra thì đồng thời dời hàng lên một vị trí. Khi lấy một phần tử ra thì đồng thời dời hàng lên một vị trí.  Chỉ dời hàng về đầu khi cuối hàng không còn chỗ Chỉ dời hàng về đầu khi cuối hàng không còn chỗ A B C D B C D B C D E Ban đầu Lấy ra 1 phần tử: dời tất cả về trước Thêm vào 1 phần tử A B C D B C D B C D E Ban đầu Lấy ra 1 phần tử Thêm vào 1 phần tử: dời tất cả về trước để trống chỗ thêm vào Biểu diễn Queue dùng mảng Biểu diễn Queue dùng mảng
  • 143. 143 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Để Để khai khai báo báo một một hàng hàng đợi đợi, , ta ta cần cần: :  một một mảng mảng một một chiều chiều Q Q, ,  hai hai biến biến nguyên nguyên f f, , r r cho cho biết biết chỉ chỉ số số của của đầu đầu và và cuối cuối của của hàng hàng đợi đợi  hằng hằng số số N N cho cho biết biết kích kích thước thước tối tối đa đa của của hàng hàng đợi đợi. .  Ngoài Ngoài ra ra, , khi khi dùng dùng mảng mảng biểu biểu diễn diễn hàng hàng đợi đợi, , cần cần dùng dùng một một giá giá trị trị đặc đặc biệt biệt, , ký ký hiệu hiệu là là NULLDATA NULLDATA, , để để gán gán cho cho những những ô ô còn còn trống trống trên trên hàng hàng đợi đợi. . Giá Giá trị trị này này là là một một giá giá trị trị nằm nằm ngoài ngoài miền miền xác xác định định của của dữ dữ liệu liệu lưu lưu trong trong hàng hàng đợi đợi.. ..
  • 144. 144 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Trạng Trạng thái thái hàng hàng đợi đợi lúc lúc bình bình thường thường: :  Trạng Trạng thái thái hàng hàng đợi đợi lúc lúc xoay xoay vòng vòng: :
  • 145. 145 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Hàng Hàng đợi đợi có có thể thể được được khai khai báo báo cụ cụ thể thể như như sau sau: : typedef struct node { int data; }; typedef struct queue { int front, rear; node list[N]; };  Do Do khi khi cài cài đặt đặt bằng bằng mảng mảng một một chiều chiều, , hàng hàng đợi đợi có có kích kích thước thước tối tối đa đa nên nên cần cần xây xây dựng dựng thêm thêm một một thao thao tác tác phụ phụ cho cho hàng hàng đợi đợi: :  Full(): (): Kiểm Kiểm tra tra xem xem hàng hàng đợi đợi có có đầy đầy chưa chưa. .
  • 146. 146 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Tạo Tạo hàng hàng đợi đợi rỗng rỗng void Init(queue &q) { q.front = q.rear = 0; }  Kiểm tra queue rỗng int Empty(queue q) { if(q.front == q.rear == 0) return 1; return 0; }
  • 147. 147 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Kiểm Kiểm tra tra hàng hàng đợi đợi đầy đầy hay hay không không int Full(queue q) { if( q.front== 0 && q.rear== N-1) return 1; if( q.front == q.rear+1) return 1; return 0; }
  • 148. 148 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Thêm Thêm một một phần phần tử tử x x vào vào cuối cuối hàng hàng đợi đợi Q Q void EnQueue(queue &q, node x) { if(!Full(q)) //Queue chưa đầy { if(Empty(q) // Queue rỗng q.front=q.rear=0; else if( q.rear==N-1) q.rear=0; else q.rear++; q.list[q.rear]=x; } }
  • 149. 149 Biểu Biểu diễn diễn Queue Queue dùng dùng mảng mảng  Trích Trích, , huỷ huỷ phần phần tử tử ở ở đầu đầu hàng hàng đợi đợi Q Q node DeQueue(queue &q) { if(!Empty(q)) { node t=q.list[q.front]; if(q.front == q.rear) Init(q); else if(q.fornt == N -1) q.front = 0; else q.front++; return t; } }
  • 150. 150 Biểu Biểu diễn diễn hàng hàng đợi đợi dùng dùng danh danh sách sách liên liên kết kết  Có Có thể thể tạo tạo một một hàng hàng đợi đợi sử sử dụng dụng một một DSLK DSLK đơn đơn. .  Phần Phần tử tử đầu đầu DSKL DSKL ( (head head) ) sẽ sẽ là là phần phần tử tử đầu đầu hàng hàng đợi đợi, , phần phần tử tử cuối cuối DSKL DSKL ( (tail tail) ) sẽ sẽ là là phần phần tử tử cuối cuối hàng hàng đợi đợi. . a1 a2 aN-2 an-1 Ñaàu haøng Cuoái haøng a0
  • 151. 151 typedef struct typedef struct node node { { int int data; data; node node *link; *link; }; }; typedef struct typedef struct queue queue { { node node *front, *rear; *front, *rear; }; }; Biểu diễn hàng đợi Biểu diễn hàng đợi dùng danh sách liên kết dùng danh sách liên kết
  • 152. 152  Tạo hàng đợi rỗng: Tạo hàng đợi rỗng: void Init(queue &q) { q.front=q.rear= NULL; } }  Kiểm tra hàng đợi rỗng : Kiểm tra hàng đợi rỗng : int Empty(queue &q) { if (q.front == NULL) return 1; // hàng đợi rỗng else return 0; }
  • 153. 153  Thêm một phần tử p vào cuối hàng đợi Thêm một phần tử p vào cuối hàng đợi void EnQueue(queue &q, node *new_ele) { if(q.front == NULL) { q.front=new_ele; q.rear=new_ele; } else { q.rear->link=new_ele; q.rear=new_ele; } }
  • 154. 154  Trích Trích phần phần tử tử ở ở đầu đầu hàng hàng đợi đợi node* DeQueue(queue &q) { if (!Empty(q)) { node *p=q.front; q.front=p->link; return p } } Biểu diễn hàng đợi Biểu diễn hàng đợi dùng danh sách liên kết dùng danh sách liên kết
  • 155. 155 Biểu Biểu diễn diễn hàng hàng đợi đợi dùng dùng danh danh sách sách liên liên kết kết  Nhận Nhận xét xét: :  Các Các thao thao tác tác trên trên hàng hàng đợi đợi biểu biểu diễn diễn bằng bằng danh danh sách sách liên liên kết kết làm làm việc việc với với chi chi phí phí O O(1). (1).  Nếu Nếu không không quản quản lý lý phần phần tử tử cuối cuối xâu xâu, , thao thao tác tác Dequeue sẽ sẽ có có độ độ phức phức tạp tạp O O( (n n). ).
  • 156. 156 Ứng Ứng dụng dụng của của hàng hàng đợi đợi  Hàng Hàng đợi đợi có có thể thể được được sử sử dụng dụng trong trong một một số số bài bài toán toán: :  Bài Bài toán toán ‘sản ‘sản xuất xuất và và tiêu tiêu thụ’ thụ’ ( (ứng ứng dụng dụng trong trong các các hệ hệ điều điều hành hành song song song song). ).  Bộ Bộ đệm đệm ( (ví ví dụ dụ: : Nhấn Nhấn phím phím   Bộ Bộ đệm đệm   CPU CPU xử xử lý lý). ).  Xử Xử lý lý các các lệnh lệnh trong trong máy máy tính tính ( (ứng ứng dụng dụng trong trong HĐH HĐH, , trình trình biên biên dịch dịch), ), hàng hàng đợi đợi các các tiến tiến trình trình chờ chờ được được xử xử lý lý, , … …. .
  • 157. Ứng dụng STACK để khử đệ Ứng dụng STACK để khử đệ quy cho bài toán tháp Hà Nội quy cho bài toán tháp Hà Nội
  • 158. 158 Bài toán Tháp Hà nội Bài toán Tháp Hà nội  Luật: Luật:  Di chuyển mỗi lần một đĩa Di chuyển mỗi lần một đĩa  Không được đặt đĩa lớn lên trên đĩa nhỏ Không được đặt đĩa lớn lên trên đĩa nhỏ
  • 159. 159 Bài toán Tháp Hà nội – Thiết kế Bài toán Tháp Hà nội – Thiết kế hàm hàm  Hàm đệ qui: Hàm đệ qui:  Chuyển (count-1) đĩa trên đỉnh của cột start sang cột Chuyển (count-1) đĩa trên đỉnh của cột start sang cột temp temp  Chuyển 1 đĩa (cuối cùng) của cột start sang cột finish Chuyển 1 đĩa (cuối cùng) của cột start sang cột finish  Chuyển count-1 đĩa từ cột temp sang cột finish Chuyển count-1 đĩa từ cột temp sang cột finish magic
  • 160. 160 Bài toán Tháp Hà nội – Mã C++ Bài toán Tháp Hà nội – Mã C++ void move(int n, char start, char finish, char temp) { if (n > 0) { move(n − 1, start, temp, finish); cout << "Move disk " << n << " from " ; cout<< start << " to " << finish << "." << endl; move(n − 1, temp, finish, start); } }

Editor's Notes

  • #6: What happens if you have written a program with an array of size 100 to store inventory items when the store you are working for adds item # 101?