Professional Documents
Culture Documents
1
Nội dung
2
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).
3
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ự.
• 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 N2 để 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.
4
1. Nhóm phương pháp căn bản
5
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
6
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;
7
Phân tích độ phức tạp của selection sort
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.
8
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.
9
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;
10
Những lưư ý về giải thuật insertion sort
• 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(N2)
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(N2)
11
Độ 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
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.
13
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; 14
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:
8 59 56 52 55 58 51 57 54
52 51 53 56 55 58 59 57 54
15
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
16
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;
17
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:
CN = 2CN/2 + N.
Số hạnh 2CN/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:
CN ≈ N lgN.
18
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 =
(n2 + n)/2 = O(n2).
Độ phức tạp trường hợp xấu nhất của Quicksort là O(n2).
19
Độ 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
với N ≥ 2 và C1 = C0 = 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.
20
Chú ý rằng, C0 + C1 + … + CN-1 thì giống hệt
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:
NCN – (N-1) CN-1 = N(N+1) – (N-1)N + 2CN-1
Từ đó ta được
NCN = (N+1)CN-1 + 2N
21
Chia cả hai vế với N(N+1) ta được hệ thức truy hồi:
CN/(N+1) = CN-1/N + 2/(N+1)
Suy ra:
CN≈ 2NlnN
22
Độ phức tạp trường hợp trung bình của
Quicksort (tt.)
Vì ta có:
lnN = (log2N).(loge2) =0.69 lgN
23
Khử đệ quy giải thuật Quicksort
Dùng ngăn xếp (stack) ta có thể chuyển Quicksort thành một
giải thuật không đệ quy
24
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).
25
Bit
Cho một khóa được diễn tả dưới dạng một số nhị phân,
một tác vụ cần thiết là trích các tập bit kề nhau từ một số.
VớI ngôn ngữ máy, các bit được trích từ số nhị phân nhờ
các tác vụ như “and” và “shift” trên các bit.
Thí dụ: Ta có thể trích hai bit đầu của một số 10 bit bằng
cách dùng tác vụ “shift right”(dịch sang phải) 8 bit rồi thực
hiện tác vụ “and” từng bit với mặt nạ 0000000011.
Trong ngôn ngữ Pascal, những tác vụ trên có thể được giả
lập bằng hai tác vụ div và mod.
26
Làm việc trên bit
Hai bit đầu của một số mười bit được trích bởi: (x div 256)
mod 4.
Trong giải thuật sắp thứ tự dựa vào cơ số, giả sử đã tồn tại
hàm bits(x,k,j :integer):integer mà trả về j bit xuất hiện cách k
bit kể từ mốc bên phải trong số x.
27
Giải thuật sắp thứ tự hoán vị cơ số
Phương pháp căn bản của giải thuật sắp thứ tự hoán vị cơ số
(exchange radix sort) là xem xét từng bit của trị khóa từ trái
sang phải.
Ý tưởng: Kết quả của sự so sánh giữa hai trị khóa chỉ tùy
thuộc vào giá trị của từng bit tại vị trí đầu tiên mà chúng khác
nhau (đọc từ trái sang phải).
28
Sắp thứ tự hoán vị cơ số
29
procedure radix_exchange(1, r, b : integer);
var t, i, j: integer;
begin
if (r >1) and (b>=0) then
begin
i:= 1; j:= r;
repeat
while (bits(a[i], b, 1)=0) and (i <j) do i:=i+1;
while (bits(a[j], b, 1)=1) and (i<j) do j:= j-1;
swap(a[i],a[j]);
until j=i;
if bits(a[r], b, 1)= 0 then j:=j +1 ;
radix_exchange(1, j-1, b-1); radix_exchange(j, r, b-1);
end
end;
30
Sắp thứ tự hoán vị cơ số (tt.)
Giả sử mảng a[1..N] chứa các số nguyên dương nhỏ hơn 232
(sao cho chúng có thể được diễn tả thành các số nhị phân 31-
bit).
Thì lịnh gọi radix_echange (1,N,30) sẽ sắp thứ tự được cho
dãy.
Biến b theo dõi các bit từ bit thứ 30 (tận cùng trái) cho đến bit
thứ 0 (tận cùng phải).
Hình vẽ sau đây minh họa sự phân hoạch theo biểu diễn nhị
phân của các trị khóa. Một phép mã hóa 5 bit được dùng cho
khóa.
31
A 00001 A 00001 A 00001 A 00001 A 00001 A 00001
S 10011 E 00101 E 00101 A 00001 A 00001 A 00001
O 01111 O 01111 A 00001 E 00101 E 00101 E 00101
Trước tiên, chúng ta xét một quá trình được gọi là trộn
(merging), thao tác phối hợp hai tập tin đã có thứ tự
thành một tập tin có thứ tự lớn hơn.
Trộn
Trongnhiều ứng dụng xử lý dữ liệu, ta phải duy trì
một tập dữ liệu có thứ tự khá lớn. Các phần tử mới
thường xuyên được thêm vào tập tin lớn.
Nhóm các phần tử được đính vào đuôi của tập tin lớn
và toàn bộ tập tin được sắp thứ tự trở lại.
Tình huống đó rất thích hợp cho thao tác trộn.
34
Trộn
Giả sử ta có hai mảng số nguyên có thứ tự a[1..M] và
b[1..N]. Ta muốn trộn chúng thành một mảng thứ ba
c[1..M+N].
i:= 1; j :=1;
for k:= 1 to M+N do
if a[i] < b[j] then
begin c [k] := a[i]; i:= i+1 end
else begin c[k] := b[j]; j := j+1 end;
36
procedure mergesort(1,r: integer);
var i, j, k, m : integer;
begin
if r-1>0 then
begin
m:=(r+1)/2; mergesort(1,m); mergesort(m+1,r);
for i := m downto 1 do b[i] := a[j];
for j :=m+1 to r do b[r+m+1-j] := a[j];
for k :=1 to r do
if b[i] < b[j] then
begin a[k] := b[i] ; i := i+1 end
else begin a[k] := b[j]; j:= j-1 end;
end;
end;
37
A S O R T I N G E X A M P L E
Thí dụ: Sắp thứ tự một
A S mảng gồm những ký tự
O R chữ
A O R S
I T
G N
G I N T
A G I N O RS T
E X
A M
A E M X
L P
E L P
A E E L M P X
A A E E G I L M N O P R S T X 38
Độ phức tạp của giải thuật Mergesort
Tính chất 4.1: Sắp thứ tự bằng phương pháp trộn cần
khoảng NlgN so sánh để sắp bất kỳ tập tin N phần tử nào.
Đối với giải thuật mergesort đệ quy, số lần so sánh được
mô tả bằng hệ thức truy hồi: CN = 2CN/2 + N, với C1 = 0.
Suy ra:
CN ≈ N lg N
Tính chất 4.2: Sắp thứ tự bằng phương pháp trộn cần
dùng chỗ bộ nhớ thêm tỉ lệ vớI N.
Ghi chú: Mergesort thì ổn định (stable) trong khi
Quicksort thì không ổn định.
39
5. Sắp thứ tự ngoại
Sắp thứ tự các tập tin lớn lưu trữ trên bộ nhớ phụ được gọi là
sắp thứ tự ngoại (external sorting).
Sắp thứ tự ngoại rất quan trọng trong các hệ quản trị cơ sở
dữ liệu (DBMSs).
Khối (block) và truy đạt khối (Block Access)
Hệ điều hành phân chia bộ nhớ phụ thành những khối có
kích thước bằng nhau. Kích thước của khối thay đổi tùy theo
hệ điều hành, nhưng thường ở khoảng 512 đến 4096 byte.
Các tác vụ căn bản trên các tập tin là
- mang một khối ra bộ đệm ở bộ nhớ chính (read)
- mang một khối từ bộ nhớ chính về bộ nhớ phụ (write).
40
Sắp thứ tự ngoại
Khi ước lượng thời gian tính toán của các giải thuật mà làm
việc trên các tập tin, chúng ta phải xét số lần mà chúng ta đọc
một khối ra bộ nhớ chính hay viết một khối về bộ nhớ phụ.
Một tác vụ như vậy được gọi là một truy đạt khối (block
access) hay một truy đạt đĩa (disk access).
khối = trang (page)
41
Xếp thứ tự ngoại bằng p.p. trộn (External Sort-
merge)
42
Xếp thứ tự ngoại bằng p.p. trộn (tt.)
43
Trộn run
• Trường hợp đặc biệt:
Giả sử số run, N, N < M. Ta có thể dành 1 trang của bộ
đệm cho mỗi run và dành chỗ bộ nhớ còn lại chứa một trang
của kết quả xuất ra. Giải thuật phần trộn run như sau:
read one block of each of the N files Ri into a buffer page in
memory;
repeat
choose the first record (in sort order) among all buffer pages;
write the tuple to the output, and delete it from the buffer page;
if the buffer page of any run Ri is empty and
not end-of-file(Ri) then
read the next block of Ri into the buffer page;
until all buffer pages are empty.
44
Trộn run (trường hợp tổng quát)
Tác vụ trộn là sự khái quát hóa của phép trộn hai đường
(two-way merge) được dùng bởi giải thuật sắp thứ tự nội
bằng phương pháp trộn. Nó trộn N run, do đó nó được gọi là
trộn nhiều đường (n-way merge).
• Trường hợp tổng quát:
Về tổng quát, nếu tập tin lớn hơn sức chứa của bộ đệm
N>M
thì không thể dành một trang trong bộ đệm cho mỗi run
trong bước trộn. Trong trường hợp này, sự trộn phải trải
qua nhiều chuyến (passes).
Vì chỉ có M-1 trang của bộ đệm dành cho các đầu vào, sự
trộn có thể tiếp nhận M-1 runs như là các đầu vào.
45
Trộn run [trường hợp tổng quát] (tt.)
46
Một thí dụ của thứ tự ngoại bằng p.p. trộn
47
a 19
d 31 a 19
g 24 g 24 b 14 a 14
a 19 c 33 a 19
d 31 b 14 d 31 b 14
c 33 c 33 e 16 c 33
b 14 e 16 g 24 d 7
e 16 d 21
r 16 d 31 a 14 d 31
d 21 m 3 d 7 e 16
m3 r 16 d 21 g 24
p 2 m3 m3
d 7 a 14 p 2 p 2
a 14 d 17 r 16 r 16
p 2
48
Độ phức tạp của xếp thứ tự ngoại
Hãy tính số truy đạt khối (block accesses) của giải thuật sắp
thứ tự ngoại bằng phương pháp trộn.
br : tổng số khối của tập tin.
Trong giai đoạn tạo run, một khối được đọc và ghi, đem lại
một tổng số 2br, truy đạt khối.
Trong mỗi chuyến trộn, từng khối của tập tin được đọc một
lần và ghi một lần.
49
Độ phức tạp của xếp thứ tự ngoại(tt)
Tổng số truy đạt đĩa cho giải thuật sắp thứ tự ngoại bằng
phương pháp trộn là:
2br + 2br logM-1(br/M) = 2br( logM-1 (br/M) +1)
50
6. Tìm kiếm tuần tự
Phương pháp đơn giản nhất để tìm kiếm là lưu trữ các mẩu
tin trong một mảng, và để tìm kiếm một mẩu tin, duyệt qua
toàn bộ mảng một cách tuần tự.
type node = record key, info: integer end;
var a: array [0..maxN] of node;
N: integer;
procedure initialize;
begin N: = 0 end;
function seq_search (v: integer, x: integer): integer;
begin
a[N+1].key: = v; /*sentinel */
if x<= N then
repeat x: = x + 1 until v = a[x].key;
seq_search: = x
end;
51
function seq_insert (v: integer): integer;
begin
N: = N+1; a[n].key : = v;
seq_insert: = N
end;
Note:
Tham số x được đưa vào để đối phó với trường hợp nhiều
mẩu tin có cùng trị khóa. Bằng cách thực hiện
t: = seq_search (v, t) bắt đầu với t = 0, ta có thể liên tiếp cho t
bằng vị trí của mỗi mẩu tin có trị khóa là v.
Nếu sự tìm kiếm thất bại, sep_search trả về trị N+1.
52
Đặc tính của tìm kiếm tuần tự (Chứng minh)
Tính chất: Tìm kiếm tuần tự cần N+1 so sánh đối với một sự
tìm kiếm không thành công và khoảng trung bình N/2 so
sánh đối với một tìm kiếm không thành công.
Chứng minh:
Trường hợp xấu nhất
Trường hợp xấu nhất xảy ra khi v là phần tử cuối cùng của
mảng hoặc v không có trong mảng.
Trong cả hai trường hợp, chúng ta có lần lượt C(N) = N và
C(N) = N+1.
53
• Trường hợp trung bình
Giả sử v có xuất hiện trong mảng và có một xác xuất đều
để xuất hiện tại một vị trí bất kỳ nào trong mảng. Và mỗi
trường hợp xảy ra với cùng xác xuất p = 1/N.
Thì
C(N) = 1.(1/N) + 2.(1/N) + …+ N.(1/N)
= (1 + 2 + …+ N).(1/N)
= (1+2+…+N)/N = N(N+1)/2.(1/N) = (N+1)/2.
54
Tìm kiếm chia đôi (binary search)
55
Độ phức tạp của giải thuật tìm kiếm chia đôi
Tính chất: Tìm kiếm chia đôi không bao giờ đòi hỏi
nhiều hơn lgN + 1 so sánh cho một sự tìm kiếm thành
công hay không thành công.
56