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.
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
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ở
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
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
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 )
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.
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;
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;
;
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?