1
Chương 2
Phân tích độ phức tạp của một số
giải thuật sắp thứ tự và tìm kiếm
2
Nội dung
1. Vài phương pháp sắp thứ tự căn bản
2. Quicksort
3. Xếp thứ tự dựa vào cơ số
4. Xếp thứ tự bằng phương pháp trộn
5. Xếp thứ tự ngoại
6. Vài phương pháp tìm kiếm căn bản
3
Nguyên tắc về sắp thứ tự
Xét những phương pháp sắp thứ tự một tập tin gồm các
mẩu tin (record) có chứa khóa (key). Khóa mà là một phần
của mẩu tin, được dùng để điều khiển việc sắp thứ tự.
Mục tiêu: sắp xếp các mẩu tin sao cho các trị khóa của
chúng có thứ tự theo một qui luật thứ tự nào đó.
Nếu các tập tin được sắp thứ tự có thể chứa trong bộ nhớ
chính thì giải thuật sắp thứ tự được gọi là sắp thứ tự nội
(internal sorting).
Việc sắp thứ tự tập tin lưu ở bộ nhớ phụ được gọi là sắp thứ
tự ngoại (external sorting).
4
Hai nhóm phương pháp sắp thứ tự
Chúng ta quan tâm đến thời gian tính toán của các
giải thuật sắp thứ tự.
1. Một nhóm gồm 4 phương pháp căn bản đòi hỏi
thời gian tính toán tỉ lệ với N
2
để sắp thứ tự N
phần tử.
2. Các phương pháp tiên tiến hơn có thể sắp thứ tự N
phần tử trong thời gian chạy tỉ lệ với NlgN.
Một đặc tính của phương pháp sắp thứ tự là tính ổn định
(stability). Một phương pháp sắp thứ tự được gọi là ổn định
khi nó bảo toàn được thứ tự tương đối của các phần tử
cùng trị khóa trong tập tin.
5
1. Nhóm phương pháp căn bản
Với nhóm này, có hai phương pháp sắp thứ tự được
chọn để khảo sát:
- sắp thứ tự bằng phương pháp chọn (selection sort)
- sắp thứ tự bằng phương pháp chèn (insertion sort)
Với mục đích tập trung vào khía cạnh giải thuật, ta sẽ
làm việc với các phương pháp mà nó chỉ sắp thứ tự
các mảng số nguyên theo thứ tự lớn dần của số.
6
Sắp thứ tự bằng phương pháp chọn
Ý tưởng:
“Trước tiên tìm phần tử nhỏ nhất trong mảng và hoán đổi
nó với phần tử đang ở vị trí thứ nhất trong mảng, và rồi
tìm phần tử nhỏ thứ nhì trong mảng và hoán đổi nó với
phần tử đang ở vị trí thứ nhì trong mảng, và cứ thế cho
đến khi toàn mảng đã được sắp thứ tự.”
390 45 45 45 45
205 205
182 182 182
182 182 205
205 205
45 390 390 390
235
235 235 235 235 390
7
Giải thuật sắp thứ tự bằng phương pháp chọn
procedure selection;
var i, j, min, t: integer;
begin
for i :=1 to N-1 do
begin
min :=i;
for j :=i+1 to N do
if a[j]<a[min] then min :=j;
t :=a[min]; a[min] :=a[i];
a[i] :=t;
end;
end;
8
Phân tích độ phức tạp của selection sort
Vòng lặp trong (tác vụ so sánh) được thực hiện với
tổng số lần như sau:
(N-1)+(N-2)+ +1 =N(N-1)/2
=O(N
2
)
Vòng lặp ngoài được thực thi N-1 lần.
Tính chất 1.1: Selection sort thực thi khoảng N hoán
vị và N
2
/2 so sánh.
Ghi chú: Thời gian tính toán của selection sort thì
độc lập đối với dữ liệu nhập.
9
Sắp thứ tự bằng phương pháp chèn
Ý tưởng :
Giải thuật xem xét từng phần tử một, chèn nó vào vị trí đúng
của nó trong nhóm các phần tử đã được sắp thứ tự rồi.
390 205 182 45 45
205 390 205 182 182
182 182 390 205 205
45 45 45 390 235
235 235 235 235 390
10
Giải thuật sắp thứ tự bằng phương pháp chèn
procedure insertion;
var i; j; v:integer;
begin
for i:=2 to N do
begin
v:=a[i]; j:= i;
while a[j-1]> v do
begin
a[j] := a[j-1]; // pull down
j:= j-1 end;
a[j]:=v;
end;
end;
11
Những lưư ý về giải thuật insertion sort
1. Chúng ta dùng một trị khóa “cầm canh” (sentinel) tại
a[0], làm cho nó nhỏ hơn phần tử nhỏ nhất trong mảng.
2. Vòng lặp ngoài của giải thuật được thực thi N-1 lần.
Trường hợp xấu nhất xảy ra khi mảng đã có thứ tự đảo
ngược. Khi đó, vòng lặp trong được thực thi với tổng số
lần sau đây:
(N-1) + (N-2) + + 1 =N(N-1)/2
=O(N
2
)
Số bước chuyển = N(N-1)/2 Số so sánh = N(N-1)/2
3. Trung bình có khoảng chừng (i-1)/2 so sánh được thực
thi trong vòng lặp trong. Do đó, trong trường hợp trung
bình, tổng số lần so sánh là:
(N-1)/2 + (N-2)/2 + + 1/2 =N(N-1)/4
=O(N
2
)
12
Độ phức tạp của sắp thứ tự bằng phương pháp
chọn và phương pháp chèn
Tính chất 1.2: Sắp thứ tự bằng phương pháp chọn
thực thi khoảng N
2
/2 so sánh và N
2
/4 hoán vị trong
trường hợp xấu nhất.
Tính chất 1.3: Sắp thứ tự bằng phương pháp chèn
thực thi khoảng N
2
/4 so sánh và N
2
/8 hoán vị trong
trường hợp trung bình.
Tính chất 1.4: Sắp thứ tự bằng phương pháp chèn có
độ phức tạp tuyến tính đối với một mảng đã gần có
thứ tự.
13
2. Giải thuật Quick sort
Giải thuật căn bản của Quick sort được phát minh năm
1960 bởi C. A. R. Hoare.
Quicksort được ưa chuộng vì nó không quá khó để hiện
thực hóa.
Quicksort chỉ đòi hỏi khoảng chừng NlgN thao tác căn bản
để sắp thứ tự N phần tử.
Nhược điểm của Quick sort gồm:
- Nó là một giải thuật đệ quy
- Nó cần khoảng N
2
thao tác căn bản trong trường hợp
xấu nhất
- Nó dễ bị lỗi khi lập trình (fragile).
14
Giải thuật căn bản của Quicksort
Quicksort là một phương pháp xếp thứ tự theo kiểu “chia
để trị”. Nó thực hiện bằng cách phân hoạch một tập tin
thành hai phần và sắp thứ tự mỗi phần một cách độc lập
với nhau.
Giải thuật có cấu trúc như sau:
procedure quicksort1(left,right:integer);
var i: integer;
begin
if right > left then
begin
i:= partition(left,right);
quicksort(left,i-1);
quicksort(i+1,right);
end;
end;
15
Phân hoạch
Phần then chốt của Quicksort là thủ tục phân hoạch
(partition), mà sắp xếp lại mảng sao cho thỏa mãn 3 điều
kiện sau:
i) phần tử a[i] được đưa về vị trí đúng đắn của nó, với một
giá trị i nào đó,
ii) tất cả những phần tử trong nhóm a[left], , a[i-1] thì nhỏ
hơn hay bằng a[i]
iii) tất cả những phần tử trong nhóm a[i+1], , a[right] thì
lớn hơn hay bằng a[i]
Example:
53 59 56 52 55 58 51 57 54
52 51 53 56 55 58 59 57 54
16
Thí dụ về phân hoạch
Giả sử chúng ta chọn phần tử thứ nhất hay phần tử tận cùng
trái (leftmost ) như là phần tử sẽ được đưa về vị trí đúng của
nó ( Phần tử này được gọi là phần tử chốt - pivot).
40 15 30 25 60 10 75 45 65 35 50 20 70 55
40 15 30 25 20 10 75 45 65 35 50 60 70 55
40 15 30 25 20 10 35 45 65 75 50 60 70 55
35 15 30 25 20 10 40 45 65 75 50 60 70 55
nhỏ hơn 40 sorted lớn hơn 40
17
Giải thuật Quicksort
procedure quicksort2(left, right: integer);
var j, k: integer;
begin
if right > left then
begin
j:=left; k:=right+1;
//start partitioning
repeat
repeat j:=j+1 until a[j] >= a[left];
repeat k:=k-1 until a[k]<= a[left];
if j< k then swap(a[j],a[k])
until j>k;
swap(a[left],a[k]); //finish partitioning
quicksort2(left,k-1);
quicksort2(k+1,right)
end;
end;
18
Phân tích độ phức tạp: trường hợp tốt nhất
Trường hợp tốt nhất xảy ra với Quicksort là khi mỗi lần
phân hoạch chia tập tin ra làm hai phần bằng nhau.
điều này làm cho số lần so sánh của Quicksort thỏa mãn hệ
thức truy hồi:
C
N
= 2C
N/2
+ N.
Số hạnh 2C
N/2
là chi phí của việc sắp thứ tự hai nửa tập tin
và N là chi phí của việc xét từng phần tử khi phân hoạch lần
đầu.
Từ chương 1, việc giải hệ thức truy hồi này đã đưa đến lời
giải:
C
N
N lgN.
19
Phân tích độ phức tạp: trường hợp xấu nhất
Một trường hợp xấu nhất của Quicksort là khi tập tin đã có
thứ tự rồi.
Khi đó, phần tử thứ nhất sẽ đòi hỏi n so sánh để nhận ra
rằng nó nên ở đúng vị trí thứ nhất. Hơn nữa, sau đó phân
đoạn bên trái là rỗng và và phân đoạn bên phải gồm n – 1
phần tử. Do đó với lần phân hoạch kế, phần tử thứ hai sẽ
đòi hỏi n-1 so sánh để nhận ra rằng nó nên ở đúng vị trí thứ
hai. Và cứ tiếp tục như thế.
Như vậy tổng số lần so sánh sẽ là:
n + (n-1) + … + 2 + 1 = n(n+1)/2 =
(n
2
+ n)/2 = O(n
2
).
Độ phức tạp trường hợp xấu nhất của Quicksort là O(n
2
).
20
Độ phức tạp trường hợp trung bình của Quicksort
Công thức truy hồi chính xác cho tổng số so sánh mà Quick
sort cần để sắp thứ tự N phần tử được hình thành một cách
ngẫu nhiên:
N
C
N
= (N+1) + (1/N) (C
k-1
+ C
N-k
)
1
với N 2 và C
1
= C
0
= 0
Số hạng (N+1) bao gồm số lần so sánh phần tử chốt với từng
phần tử khác, thêm hai lần so sánh để hai pointer giao nhau.
Phần còn lại là do sự kiện mỗi phần tử ở vị trí k có cùng xác
xuất 1/N để được làm phần tử chốt mà sau đó chúng ta có
hai phân đoạn với số phần tử lần lượt là k-1 và N-k.
21
Chú ý rằng, C
0
+ C
1
+ … + C
N-1
thì giống hệt
C
N-1
+ C
N-2
+… + C
0
, nên ta có
N
C
N
= (N+1) + (1/N) 2C
k-1
1
Ta có thể loại trừ đại lượng tính tổng bằng cách nhân cả hai vế
với N và rồi trừ cho cùng công thức nhân với N-1:
NC
N
– (N-1) C
N-1
= N(N+1) – (N-1)N + 2C
N-1
Từ đó ta được
NC
N
= (N+1)C
N-1
+ 2N
22
Chia cả hai vế với N(N+1) ta được hệ thức truy hồi:
C
N
/(N+1) = C
N-1
/N + 2/(N+1)
= C
N-2
/(N-1) + 2/N + 2/(N+1)
.
.
N
= C
2
/3 + 2/(k+1)
3
N N
C
N
/(N+1) 2 1/k 2 1/x dx = 2lnN
1 1
Suy ra:
C
N
2NlnN
23
Độ phức tạp trường hợp trung bình của
Quicksort (tt.)
Vì ta có:
lnN = (log
2
N).(log
e
2) =0.69 lgN
2NlnN 1.38 NlgN.
Tổng số so sánh trung bình của Quicksort chỉ khoảng
chừng 38% cao hơn trong trường hợp tốt nhất.
Mệnh đề. Quicksort cần khoảng 2NlnN so sánh trong
trường hợp trung bình.
24
Khử đệ quy giải thuật Quicksort
procedure quicksort3;
var t, i, left, right : integer;
begin
left :=1; right:= N;
stackinit;
push(left); push(right);
repeat
if right > left then
begin
i=: partition(left,right);
if (i –left) > (right –i) then
begin push(left); push(i-1);
left := i+1 end
else
begin
push (i+1);push(right);
right:=i-1
end;
end
else
begin right := pop; left := pop
end;
until stackempty;
end;
Dùng ngăn xếp (stack) ta có thể chuyển Quicksort thành một
giải thuật không đệ quy
25
3. Sắp thứ tự dựa vào cơ số
Trong nhiều ứng dụng, các trị khóa có thể là những khóa
thuộc một tầm hạn định nào đó.
Các phương pháp sắp thứ tự mà lợi dụng tính chất số của
các khóa được gọi là sắp thứ tự dựa vào cơ số (radix sort).
Những phương pháp này không chỉ so sánh các trị khóa
chúng xử lý và so sánh các phần của khóa.
Sắp thứ tự dựa vào cơ số coi các trị khóa như là những số
được biểu diễn ở dạng hệ cơ số M và làm việc với từng ký
số (digit) đơn lẻ.
Với hầu hết mọi máy tính, thật tiện lợi để làm việc với cơ
số 2 (M =2), hơn là cơ số thập phân (M =10).