Tải bản đầy đủ (.pdf) (47 trang)

Bài giảng cấu trúc dữ liệu chương 2 tìm kiếm và sắp xếp

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (650.66 KB, 47 trang )

Đ
Đ


i H
i H


c Sư Ph
c Sư Ph


m Tp. H
m Tp. H


Ch
Ch
í
í
Minh
Minh
Chương 2: Tìm kiếm & Sắp xếp
C
C


U TR
U TR
Ú
Ú


C D
C D


LI
LI


U 1
U 1
2
2
Tìm kiếm & Sắp xếp
Mục tiêu:
• Giới thiệu một số thuật toán tìm kiếm và sắp xếp nội.
• Phân tích, đánh giá độ phức tạp của các giải thuật tìm
kiếm, sắp xếp.
Nội dung:
• Nhu cầu tìm kiếm và sắp xếp dữ liệu trong một hệ
thống thông tin.
• Các giải thuật tìm kiếm nội.
• Các giải thuật sắp xếp nội.
3
3
Các giải thuật
tìm kiếm nội
• Tìm tuần tự
• Tìm nhị phân
Tìm kiếm
4

4
Các giải thuật tìm kiếm nội
Bài toán: Tìm vò trí xuất hiện của phần tử có
giá trò x trên danh sách đặc a
•Tập dữ liệu được lưu trữ là dãy số a
1
, a
2
, ,a
N
int a[N];
•Khoá cần tìm là x
int x;
5
5
Tìm kiếm tuần tự
• Bước 1: i = Vò trí đầu;
• Bước 2: Nếu a[i] = x : Tìm thấy. Dừng, vò trí
xuất hiện: i
• Bước 3 : i = Vò trí kế(i);// xét tiếp phần tử kế
trong mảng
• Bước 4: Nếu i >Vò trí cuối: //Hết mảng
Không tìm thấy. Dừng.
Ngược lại: Lặp lại Bước 2.
6
6
Tìm kiếm tuần tự
• Ví dụ: Cho dãy số a
1228516415
• Giá trò cần tìm: 8

• i = 1
7
7
Tìm kiếm tuần tự
• i = 2
• i = 3
8
8
T
TT

ìì
ìm kie
m kiem kie
m kiế
áá
ám tua
m tuam tua
m tuầ
àà
àn t
n tn t
n tự
ựự

int LinearSearch(int a[], int N, int x)
{
for (int i=0; (i<N)&&(a[i]!=x ); i++);
if (i<N)
return i; // a[i] là phần tử có khoá x

return -1; // tìm hết mảng nhưng không có x
}
9
9
Tìm kiếm tuần tự
• Cải tiến cài đặt: dùng phương pháp “đặt lính
canh”
– Đặt thêm một phần tử có giá trò x vào cuối mảng
– Bảo đảm luôn tìm thấy x trong mảng
– Sau đó dựa vào vò trí tìm thấy để kết luận.
10
10
Tìm kiếm tuần tự
int LinearSearch(int a[], int N, int x)
{
// mảng gồm N phần tử từ a[0] a[N-1]
a[N] = x; // thêm lính canh vào cuối dãy
for (int i=0; (a[i]!=x); i++);
if (i<N)
return i; // a[i] là phần tử có khoá x
return -1; // tìm hết mảng nhưng không có x
}
11
11
Tìm kiếm tuần tự
• Đánh giá giải thuật:
• Vậy giải thuật tìm tuần tự có độ phức tạp
tính toán cấp n: T(n) = O(n)
12
12

Tìm kiếm tuần tự

Nhận xét:
– Giải thuật tìm tuyến tính không phụ thuộc vào
thứ tự của các phần tử trong danh sách, do vậy
đây là phương pháp tổng quát nhất để tìm kiếm
trên một danh sách bất kỳ.
– Một thuật toán có thể được cài đặt theo nhiều
cách khác nhau, kỹ thuật cài đặt ảnh hưởng đến
tốc độ thực hiện của thuật toán.
13
13
Tìm kiếm nhò phân
• Đối với những dãy đã sắp thứ tự (giả sử thứ tự
tăng), các phần tử trong dãy có quan hệ
a
i -1

≤≤
≤ a
i

≤≤
≤ a
i+1
Nếu x > a
i
thì x chỉ có thể xuất hiện trong
đoạn [a
i+1

,a
N
] của dãy
Nếu x < a
i
thì x chỉ có thể xuất hiện trong
đoạn [a
1
,a
i-1
] của dãy
14
14
Tìm kiếm nhò phân
• Ý tưởng của giải thuật là tại mỗi bước tiến
hành so sánh x với phần tử nằm ở vò trí giữa
của dãy tìm kiếm hiện hành, dựa vào kết quả
so sánh này để quyết đònh giới hạn dãy tìm
kiếm ở bước kế tiếp là nửa trên hay nửa dưới
của dãy tìm kiếm hiện hành
15
15
Tìm kiếm nhò phân
Bước 1: left = VTĐ; right = VTC;
Bước 2: Trong khi left ≤
≤≤
≤ right lặp: //đoạn tìm kiếm chưa rỗng
Bước 2.1: mid = (left+right)/2; // lấy mốc so sánh
Bước 2.2: Nếu a[mid] = x: //Tìm thấy.
Dừng, vò trí xuất hiện: mid

Bước 2.3: Nếu a[mid] > x: //tìm x trong dãy con a
left
a
mid -1
right = mid - 1;
Ngược lại //tìm x trong dãy con a
mid +1
a
right
left = mid + 1;
//Hết lặp
Bước 3: Dừng, không tìm thấy.
16
16
Tìm kiếm nhò phân
• Ví dụ: Cho dãy số a gồm 8 phần tử:
1245 6 8 12 15
• Giá trò cần tìm là 8
17
17
Tìm kiếm nhò phân
• left = 1, right = 8, mid = 4
18
18
Tìm kiếm nhò phân
• left = 5, right = 8, mid = 6
19
19
Tìm kiếm nhò phân
int BinarySearch(int a[],int N,int x )

{
int left =0, right = N-1, midle;
while (left <= right)
{
midle = (left + right)/2;
if (x == a[midle])
return midle;//Tìm thấy x tại mid
if (x<a[midle])right = midle -1;
else left = midle +1;
}
return -1; // trong dãy không có x
}
20
20
Tìm kiếm nhò phân
• Đánh giá giải thuật:
• Giải thuật tìm nhò phân có độ phức tạp
tính toán cấp logn:
T(n) = O(log
2
n)
21
21
Tìm kiếm nhò phân

Nhận xét:
– Giải thuật tìm nhò phân dựa vào quan hệ giá trò
của các phần tử mảng để đònh hướng trong quá
trình tìm kiếm, do vậy chỉ áp dụng được cho
những dãy đã có thứ tự.

– Giải thuật tìm nhò phân tiết kiệm thời gian hơn
rất nhiều so với giải thuật tìm tuần tự do
T
nhò phân
(n) = O(log
2
n) < T
tuần tự
(n) = O(n).
22
22
Tìm kiếm nhò phân

Nhận xét:
– Khi muốn áp dụng giải thuật tìm nhò phân cần
phải xét đến thời gian sắp xếp dãy số để thỏa
điều kiện dãy số có thứ tự. Thời gian này không
nhỏ, vàkhi dãy sốbiến động cần phải tiến hành
sắp xếp lại => khuyết điểm chính cho giải thuật
tìm nhò phân.
– Cần cân nhắc nhu cầu thực tế để chọn một trong
hai giải thuật tìm kiếm trên sao cho có lợi nhất.
23
23
Đònh nghóa bài toán sắp xếp
• Sắp xếp là quá trình xử lý một danh sách các
phần tử (hoặc các mẫu tin) để đặt chúng theo
một thứ tự
thỏa mãn một tiêu chuẩn nào đó
dựa trên nội dung thông tin lưu giữ tại mỗi

phần tử.
• Lưu ý
: Thứ tự được đề cập ở đây là một thứ
tự tổng quát.
• Ví dụ: Hãy đònh nghóa một thứ tự để dãy số
sau là dãy tăng theo thứ tự này.
1 3 5 7 2220106
24
24
Khái niệm nghòch thế
• Khái niệm nghòch thế:
– Xét một mảng các số a
0
, a
1
, … a
n
.
– Nếu cói<j vàa
i
> a
j
, thì ta gọi đó là một nghòch
thế.
• Mảng chưa sắp xếp sẽ có nghòch thế.
• Mảng đã có thứ tự sẽ không chứa nghòch thế.
a
0

≤≤

≤ a
1

≤≤
≤ … ≤
≤≤
≤ a
n
25
25
Các phương pháp sắp xếp thông dụng
• Selection sort
• Insertion sort
• Interchange sort
• Bubble sort
• Shaker sort
• Binary Insertion
sort
• Shell sort
• Heap sort
• Quick sort
• Merge sort
• Radix sort
• …
Đ
Đ
ơn gia
ơn gia
û
û

n,
n,
Chi ph
Chi ph
í
í
cao
cao
Ph
Ph


c ta
c ta
ï
ï
p hơn
p hơn
Hie
Hie
ä
ä
u qua
u qua
û
û
cao
cao



ù
ù
p thua
p thua
ä
ä
t toa
t toa
ù
ù
n
n
kha
kha
ù
ù
c
c
26
26
Selection sort – Ý tưởng
• Nhận xét: Mảng có thứ tự thì
a
i
= min(a
i
, a
i+1
, …, a
n-1

)


Ý tưởng: mô phỏng một trong những cách sắp
xếp tự nhiên nhất trong thực tế:
– Chọn phần tử nhỏ nhất trong N phần tử ban đầu,
đưa phần tử này về vò trí đúng là đầu dãy hiện
hành
– Xem dãy hiện hành chỉ còn N-1 phần tử của dãy
ban đầu, bắt đầu từ vò trí thứ 2; lặp lại quá trình
trên cho dãy hiện hành đến khi dãy hiện hành
chỉ còn 1 phần tử.
27
27
Selection sort – Thuật toán
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1 : i = Vò trí đầu;
• Bước 2 : Tìm phần tử a[min] nhỏ nhất trong dãy
hiện hành từ a[i] đến a[N]
• Bước 3 : Nếu min

≠≠
≠ i: Hoán vò a[min] và a[i]
• Bước 4 : Nếu i chưa là Vò trí cuối
» i = Vò trí kế(i);
» Lặp lại Bước 2
Ngược lại: Dừng. //N phần tử đã nằm
đúng vò trí.
28

28
Selection sort – Ví dụ
2 8 5 1 6 4 1512
i
min
23456781
Find MinPos(1, 8)
Swap(a
i
, a
min
)
29
29
Selection sort – Ví duï
2 8 5 12 6 4 151
i
min
23456781
Find MinPos(2, 8)
Swap(a
i
, a
min
)
30
30
Selection sort – Ví duï
2 8 5 12 6 4 151
i

min
23456781
Find MinPos(3, 8)
Swap(a
i
, a
min
)
31
31
Selection sort – Ví duï
2 4 5 12 6 8 151
i
min
23456781
Find MinPos(4, 8)
Swap(a
i
, a
min
)
32
32
Selection sort – Ví duï
2 4 5 12 6 8 151
i
min
23456781
Find MinPos(5, 8)
Swap(a

i
, a
min
)
33
33
Selection sort – Ví dụ
2 4 5 6 12 8 151
i
min
23456781
Find MinPos(6, 8)
Swap(a
i
, a
min
)
34
34
Selection sort – Ví dụ
2 4 5 6 8 12 151
i
min
23456781
Find MinPos(7, 8)
Swap(a
i
, a
min
)

12
15
35
35
Selection sort
void SelectionSort(int a[],int N )
{
int min; // chỉ số phần tử nhỏ nhất trong dãy hiện hành
for (int i=0; i<N-1 ; i++)
{
min = i;
for(int j = i+1; j < N ; j++)
if (a[j] < a[min])
min = j; // ghi nhận vò trí phần tử nhỏ nhất
if (min != i)
Swap(a[min], a[i]);
}
}
36
36
• Số lần hoán vò (một hoán vò bằng 3 phép
gán) phụ thuộc vào tình trạng ban đầu
của dãy số
Selection sort – Đánh giá giải thuật
37
37
Selection sort – Đánh giá giải thuật
• Ởû lượt thứ i, cần (N-i) lần so sánh để xác
đònh phần tử nhỏ nhất hiện hành.
• Số lượng phép so sánh không phụ thuộc vào

tình trạng của dãy số ban đầu.
• Trong mọi trường hợp, số lần so sánh là:
2
1)n(n
i)(n
1n
1i

=−


=
38
38
Insertion Sort – Ý tưởng
• Nhận xét: mọi dãy a
1
, a
2
, , a
n
luôn có i-1 phần tử
đầu tiên a
1
, a
2
, ,a
i-1
đã có thứ tự (2 ≤ i).



Ý tưởng chính: tìm cách chèn phần tử a
i
vào vò trí
thích hợp của đoạn đã được sắp để có dãy mới a
1
,
a
2
, ,a
i
trở nên có thứ tự.
– Vò trí này chính là pos thỏa a
pos-1
≤ a
i
<a
pos
(1≤
≤≤
≤pos≤
≤≤
≤i).
Chi tiết hơn:
– Dãy ban đầu a
1
, a
2
, , a
n

, xem như đã có đoạn gồm một
phần tử a
1
đã được sắp.
– Thêm a
2
vào đoạn a
1
sẽ có đoạn a
1
a
2
được sắp
– Thêm a
3
vào đoạn a
1
a
2
để có đoạn a
1
a
2
a
3
được sắp
– Tiếp tục cho đến khi thêm xong a
N
vào đoạn a
1

a
2
a
N-1
sẽ
có dãy a
1
a
2
a
N
được sắp.
39
39
Insertion Sort – Thuật toán
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1
: i = 2; // giả sử có đoạn a[1] đã được sắp
• Bước 2
: x = a[i]; Tìm vò trí pos thích hợp trong đoạn
a[1]
đến a[i] để chèn x vào
• Bước 3
: Dời chỗ các phần tử từ a[pos] đến a[i-1] sang
phải 1 vò trí để dành chổ cho x
• Bước 4
: a[pos] = x; // có đoạn a[1] a[i] đã được sắp
• Bước 5
: i = i+1;

Nếu i ≤
≤≤
≤ n : Lặp lại Bước 2.
Ngược lại : Dừng.
40
40
Insertion Sort – Ví dụ
2 8 5 1 6 4 1512
23456781
41
41
2 8 5 1 6 4 1512
i
x
23456781
pos
2
Insertion Sort – Ví duï
Insert a
2
into (1, 2)
42
42
12 8 5 1 6 4 152
i
x
23456781
pos
Insertion Sort – Ví duï
Insert a

3
into (1, 3)
8
43
43
8 12 5 1 6 4 152
i
x
23456781
pos
Insertion Sort – Ví duï
Insert a
4
into (1, 4)
5
44
44
5 8 12 1 6 4 152
i
x
23456781
pos
Insertion Sort – Ví duï
Insert a
5
into (1, 5)
1
45
45
2 5 8 12 6 4 151

i
x
23456781
pos
Insertion Sort – Ví duï
Insert a
6
into (1, 6)
6
46
46
2 5 6 8 12 4 151
i
x
23456781
pos
Insertion Sort – Ví duï
Insert a
7
into (1, 7)
4
47
47
2 4 5 6 8 12 151
i
x
23456781
pos
Insertion Sort – Ví duï
Insert a

8
into (1, 8)
15
48
48
2 4 5 6 8 12 151
pos
23456781
Insertion Sort – Ví duï
49
49
Insertion Sort – Cài đặt
void InsertionSort(int a[], int N )
{
int pos, i;
int x;
//lưu trữ a[i] tránh bò ghi đè khi dời chỗ các phần tử.
for(int i=1 ; i<N ; i++) //đoạn a[0] đã sắp
{
x = a[i];
for(pos=i;(pos>0)&&(a[pos-1]>x);pos )
a[pos] = a[pos-1];
a[pos] = x;// chèn x vào dãy
}
}
50
50
Insertion Sort – Nhận xét
• Khi tìm vò trí thích hợp để chèn a[i] vào đoạn
a[0] đến a[i-1], do đoạn đã được sắp 


 có thể
sử dụng giải thuật tìm nhò phân để thực hiện
việc tìm vò trí pos 

 giải thuật sắp xếp chèn
nhò phân Binary Insertion Sort
– Lưu ý: Chèn nhò phân chỉ làm giảm số lần so sánh,
không làm giảm số lần dời chỗ.
• Ngoài ra, có thể cải tiến giải thuật chèn trực
tiếp với phần tử cầm canh để giảm điều kiện
kiểm tra khi xác đònh vò trí pos.
51
51
Binary Insertion Sort – Cài đặt
void BInsertionSort(int a[], int N )
{
int l,r,m,i;
int x;//lưu trữ giá trò a[i] tránh bò ghi đè khi dời chỗ các phần
tử.
for(int i=1 ; i<N ; i++)
{ x = a[i]; l = 1; r = i-1;
while(l<=r) // tìm vò trí chèn x
{ m = (l+r)/2; // tìm vò trí thích hợp m
if(x < a[m]) r = m-1;
else l = m+1;
}
for(int j = i ; j >l ; j )
a[j] = a[j-1]; // dời chỗ các phần tử sẽ đứng sau
x

a[l] = x; // chèn x vào dãy
}
}
52
52
Insertion Sort – Đánh giá giải thuật
• Các phép so sánh xảy ra trong mỗi vòng lặp tìm vò trí
thích hợp pos. Mỗi lần xác đònh vò trí pos đang xét
không thích hợp 

 dời chỗ phần tử a[pos-1] đến vò trí
pos.
• Giải thuật thực hiện tất cả N-1 vòng lặp tìm pos, do số
lượng phép so sánh và dời chỗ này phụ thuộc vào tình
trạng của dãy số ban đầu, nên chỉ có thể ước lược trong
từng trường hợp như sau:
Phương pháp đổi chỗ trực tiếp
Interchange Sort
54
54
Interchange Sort – Ý tưởng
• Nhận xét: Để sắp xếp một dãy số, ta có
thể xét các nghòch thế có trong dãy và
làm triệt tiêu dần chúng đi.


 Ý tưởng chính:
– Xuất phát từ đầu dãy, tìm tất cả nghòch thế
chứa phần tử này, triệt tiêu chúng bằng
cách đổi chỗ phần tử này với phần tử tương

ứng trong cặp nghòch thế.
– Lặp lại xử lý trên với các phần tử tiếp theo
trong dãy
55
55
Interchange Sort – Thuật toán
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1 : i = 1; // bắt đầu từ đầu dãy
• Bước 2 : j = i+1; //tìm các cặp phần tử
a[j] < a[i], j>i
• Bước 3 : Trong khi j ≤ N thực hiện
• Nếu a[j]<a[i]: a[i]↔a[j];
•j = j+1;
• Bước 4 : i = i+1;
– Nếu i < n: Lặp lại Bước 2.
– Ngược lại: Dừng.
56
56
Interchange Sort – Ví dụ
2 8 5 1 6 4 1512
23456781
i
j
1
57
57
Interchange Sort – Ví duï
12 8 5 2 6 4 151
23456781

i
j
2
58
58
Interchange Sort – Ví duï
2 12 8 5 6 4 151
23456781
i
j
4
59
59
Interchange Sort – Ví duï
2 4 12 8 6 5 151
23456781
i
j
5
60
60
Interchange Sort – Ví duï
2 4 5 6 8 12 151
23456781
61
61
Interchange Sort - Cài đặt
void InterchangeSort(int a[], int N)
{
int i, j;

for (i = 0 ; i<N-1 ; i++)
for (j =i+1; j < N ; j++)
if(a[j]< a[i]) //nếu có nghòch thế
thì đổi chỗ
Swap(a[i],a[j]);
}
62
62
Interchange Sort
Đánh giá giải thuật
• Số lượng các phép so sánh xảy ra không phụ
thuộc vào tình trạng của dãy số ban đầu
• Số lượng phép hoán vò thực hiện tùy thuộc
vào kết quả so sánh
Phương pháp nổi bọt
Bubble sort
64
64
Bubble sort – Ý tưởng
• Ý tưởng chính:
– Xuất phát từ cuối (đầu) dãy, đổi chỗ các
cặp phần tử kế cận để đưa phần tử nhỏ
(lớn) hơn trong cặp phần tử đó về vò trí
đúng đầu (cuối) dãy hiện hành, sau đó sẽ
không xét đến nó ở bước tiếp theo,
– Ở lần xử lý thứ i có vò trí đầu dãy là i
– Lặp lại xử lý trên cho đến khi không còn
cặp phần tử nào để xét.
65
65

Bubble sort – Thuật toán
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1 : i = Vò trí đầu;
• Bước 2 : j = Vò trí cuối;//Duyệt từ cuối dãy ngược
về vò trí i
– Trong khi (j > i) thực hiện:
• Nếu a[j]<a[j-1]: a[j]↔
↔↔
↔a[j-1];//xét cặp phần tử kế cận
• j = Vò trí trước(j);
• Bước 3 : i = Vò trí kế(i); // lần xử lý kế tiếp
– Nếu i = Vò trí cuối: Dừng. // Hết dãy.
– Ngược lại : Lặp lại Bước 2.
66
66
Bubble Sort – Ví dụ
2 8 5 1 6 4 1512
23456781
i
j
1
67
67
Bubble Sort – Ví dụ
12 2 8 5 4 6 151
23456781
i
j
2

68
68
Bubble Sort – Ví dụ
2 12 4 8 5 6 151
23456781
i
j
4
69
69
Bubble Sort – Ví duï
2 4 12 8 5 6 151
23456781
i
j
5
70
70
Bubble Sort – Ví duï
2 4 5 12 8 6 151
23456781
i
j
6
71
71
Bubble Sort – Ví duï
2 4 5 6 12 8 151
23456781
i

j
8
72
72
Bubble Sort – Ví duï
2 4 5 6 8 12 151
23456781
i
j
15
12
73
73
Bubble sort - Cài đặt
void BubbleSort(int a[], int N)
{
int i, j;
for (i = 0 ; i < N-1 ; i++)
for (j = N-1; j>i ; j )
if(a[j]< a[j-1])
Swap(a[j], a[j-1]);
}
74
74
Bubble sort - Đánh giá giải thuật
• Số lượng các phép so sánh xảy ra không phụ
thuộc vào tình trạng của dãy số ban đầu
• Số lượng phép hoán vò thực hiện tùy thuộc
vào kết quả so sánh
75

75
• Khuyết điểm:
– Không nhận diện được tình trạng dãy đã có
thứ tự hay có thứ tự từng phần.
– Các phần tử nhỏ được đưa về vò trí đúng rất
nhanh, trong khi các phần tử lớn lại được
đưa về vò trí đúng rất chậm.
Bubble sort - Đánh giá giải thuật
76
76
Bubble sort – Cải tiến
• Giải thuật ShakerSort:
– Dựa trên nguyên tắc đổi chỗ trực tiếp
– Tìm cách khắc phục các nhược điểm của
BubleSort
• Trong mỗi lần sắp xếp, duyệt mảng theo 2 lượt
từ 2 phía khác nhau :
– Lượt đi: đẩy phần tử nhỏ về đầu mảng
– Lượt về: đẩy phần tử lớn về cuối mảng
• Ghi nhận lại những đoạn đã sắp xếp nhằm tiết
kiệm các phép so sánh thừa.
77
77
Giải thuật ShakerSort
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1 :
– l = 1; r = n; //từ l đến r là đoạn cần được sắp xếp
– k = n; // ghi nhận lại vò trí k xảy ra hoán vò sau cùng
// để làm cơ sở thu hẹp đoạn l đến r

• Bước 2 :
– Bước 2a : j = r ; // đẩy phần tử nhỏ về đầu mảng
• Trong khi (j > l) :
– Nếu a[j]<a[j-1]: a[j] ↔
↔↔
↔ a[j-1];
» k = j; //lưu lại nơi xảy ra hoán vò
– j = j-1;
• l = k; //loại bớt các phần tử đã có thứ tự ở đầu dãy
78
78
Giải thuật ShakerSort
• Bước 2 :
– Bước 2b : j = l ; // đẩy phần tử lớn về cuối mảng
• Trong khi (j < r) :
– Nếu a[j]>a[j+1]: a[j] ↔
↔↔
↔ a[j+1];
» k = j;//lưu lại nơi xảy ra hoán vò
– j = j+1;
• r = k; //loại bớt các phần tử đã có thứ tự ở cuối dãy
• Bước 3 : Nếu l < r: Lặp lại Bước 2.
79
79
Sắp xếp cây - Heap sort
• Khi tìm phần tử nhỏ nhất ở bước i, phương
pháp sắp xếp chọn trực tiếp không tận dụng
được các thông tin đã có được do các phép so
sánh ở bước i-1.
• Giải thuật Heap Sort khắc phục nhược điểm

này bằng cách chọn ra được một cấu trúc dữ
liệu cho phép tích lũy các thông tin về sự so
sánh giá trò các phần tử trong quá trình sắp
xếp.
80
80
Sắp xếp cây - Heap sort
• Xét dãy số : 5 2 6 4 8 1
• Giả sử các phần tử của dãy được bố trí
theo quan hệ so sánh và tạo thành sơ
đồ dạng cây:
81
81
Sắp xếp cây - Heap sort
• Phần tử ở mức i chính là phần tử lớn trong cặp
phần tử tương ứng ở mức i+1

⇒⇒
⇒ phần tử ở mức 0 (nút gốc của cây) luôn là phần tử
lớn nhất của dãy.
• Nếu loại bỏ phần tử gốc ra khỏi cây (nghóa là đưa
phần tử lớn nhất về đúng vò trí), thì việc cập nhật
cây chỉ xảy ra trên những nhánh liên quan đến
phần tử mới loại bỏ, còn các nhánh khác được bảo
toàn, nghóa là bước kế tiếp có thể sử dụng lại các
kết quả so sánh ở bước hiện tại.
82
82
Sắp xếp cây - Heap sort
• Loại bỏ 8 ra khỏi cây và thế vào các chỗ

trống giá trò -∞
∞∞
∞ để tiện việc cập nhật lại cây :
83
83
Sắp xếp cây - Heap sort
• Toàn bộ nhánh trái của cây cũ được bảo
toàn

⇒⇒
⇒ Bước kế tiếp để chọn được phần tử lớn
nhất hiện hành là 6, chỉ cần làm thêm
một phép so sánh 1 với 6.
84
84
Sắp xếp cây - Heap sort
• Tiến hành nhiều lần việc loại bỏ phần tử gốc của
cây cho đến khi tất cả các phần tử của cây đều là -

∞∞
∞, khi đó xếp các phần tử theo thứ tự loại bỏ trên
cây sẽ có dãy đã sắp xếp.
• Để cài đặt thuật toán hiệu quả, cần phải tổ chức
một cấu trúc lưu trữ dữ liệu cókhảnăng thểhiện
được quan hệ của các phần tử trong cây với n ô nhớ
thay vì 2n-1 như trong ví dụ.
• Khái niệm heap và phương pháp sắp xếp Heapsort
do J.Williams đề xuất đã giải quyết được các khó
khăn trên.
85

85
Sắp xếp cây - Heap sort
• Đònh nghóa heap:
– Heap là một dãy các phần tử a
left
, a
left+1
, ,
a
right
thoả các quan hệ:
• a
i

≥≥
≥ a
2i
• a
i

≥≥
≥ a
2i+1
với ∀
∀∀
∀i ∈
∈∈
∈ [left, right]
– Khi đó (a
i

, a
2i
), (a
i
,a
2i+1
) được gọi là các cặp
phần tử liên đới.
– Heap được đònh nghóa như trên được dùng
trong trường hợp sắp xếp tăng dần, khi sắp
xếp giảm dần phải đổi chiều các quan hệ.
86
86
Ví dụ dãy là heap:
12 8 5 1 4 6 215
23456781
87
87
Sắp xếp cây – Heap sort
a
2
a
3
a
4
a
5
a
6
a

7
a
8
a
1
Các phần tử
của dãy được
biểu diễn theo
các mối quan
hệ liên đới
88
88
Sắp xếp cây - Heap sort
• Một số tính chất của Heap:
– Tính chất 1: Nếu a
left
, a
left+1
, …, a
right
là một
heap thì khi cắt bỏ một số phần tử ở hai
đầu của heap, dãy con còn lại vẫn là một
heap.
– Tính chất 2: Nếu a
1
, a
2
, …, a
n

là một heap
thì phần tử a
1
(đầu heap) luôn là phần tử
lớn nhất trong heap.
– Tính chất 3: Mọi dãy con a
left
, a
left+1
, ,
a
right
thỏa: 2left > right đều là heap.
89
89
Ví dụ các tính chất của heap:
12 8 5 1 6 4 215
23456781
12 8 5 1 6 4
1 6 4 2
90
90
Sắp xếp cây - Heap sort
• Sắp xếp dãy tăng dần qua 2 giai đoạn:
– Giai đoạn 1: Dựa vào tính chất 3 của heap
để hiệu chỉnh dãy ban đầu thành heap
– Giai đoạn 2: Dựa vào các tính chất 1 và 2
của heap để sắp xếp heap có được sau giai
đoạn 1 thành dãy tăng dần
91

91
Heap sort – Giai đoạn 1
• Vấn đề: Đổi chổ một số phần tử trên
dãy a
1
, …, a
N
để dãy trở thành heap.
• Ý tưởng: theo tính chất 3, dãy con a
n/2+1
,
a
n/2+2
a
n
đương nhiên là heap. Lần lượt
thêm vào phía trước dãy các phần tử
a
n/2
, a
n/2-1
, …, a
1
; mỗi bước thêm vào cần
hiệu chỉnh vò trí các phần tử theo mối
quan hệ liên đới ta sẽ nhận được heap
mong muốn.
92
92
Heap sort – Giai đoạn 1

//input: dãy (a, N)
//output: dãy (a, N) là một heap
• Bước 1: left = N/2; //Thêm các phần tử
a
left
, , a
1
vào heap
• Bước 2: Trong khi left > 0
//Lưu ý: đoạn a
left+1
, …, a
N
đã là heap
• Bước 21: Hiệu chỉnh đoạn a
left
, …, a
N
thành heap
• Bước 22: left = left - 1;
//Hết lặp
93
93
Heap sort – Giai ñoaïn 1
2 8 5 1 6 4 1512
23456781
94
94
15
Heap sort – Giai ñoaïn 1

2 8 5 1 6 412
23456781
left
joint
joint
curr
5
95
95
Heap sort – Giai ñoaïn 1
2 8 15 1 6 4 512
23456781
left
joint
jointcurr
joint
8
96
96
Heap sort – Giai ñoaïn 1
15 8 5 1 6 4 212
23456781
left
joint
jointcurr
97
97
Heap sort – Giai đoạn 1
12 8 5 1 6 4 215
23456781

98
98
Heap sort – Giai đoạn 2
• Vấn đề: Sắp xếp heap a
1
, …, a
N
thành dãy tăng
dần
//Đặt: right = N



dãy a
1
, …, a
right
là heap.
• Ý tưởng:
– Theo tính chất 2: a
1
sẽ là phần tử lớn nhất, vì vậy vò
trí đúng của a
1
phải là right - cuối dãy.
Đổi chổ (a
1
, a
right
) 


 được thêm một phần tử ở đúng vò trí
Theo tính chất 3: dãy con a
2
, …, a
right-1
vẫn là heap
 Giảm right, thêm a
1
vào dãy và hiệu chỉnh lại
 dãy a
1
, …, a
right
là heap.
99
99
Heap sort – Giai đoạn 2
//input: dãy (a, N) là heap
//output: dãy (a, N) sắp tăng dần
• Bước 1: right = N; //Bắt đầu thực hiện từ cuối
dãy
• Bước 2: Trong khi right > 1
//Đưa phần tử lớn nhất (a
1
)về vò trí right
• Bước 2.1: Hoánvò (a
1
, a
right

);
//Loại bỏ phần tử lớn nhất ra khỏi heap
• Bước 2.2: right := right -1;
• Bước 2.3: Hiệu chỉnh đoạn a
1
, a
2
, …, a
right
thành heap
//Hết lặp
100
100
Heap sort – Giai đoạn 2
12 8 5 1 6 4 215
23456781
right
Swap(a
1
, a
right
)

×