S P X PẮ Ế
Nguy n Văn Linhễ
M c tiêuụ
Sau khi hoàn t t bài h c này b n c n ph i:ấ ọ ạ ầ ả
Hi u các gi i thu t s p x p.ể ả ậ ắ ế
V n d ng đ c gi i thu t đ minh h a vi c s p ậ ụ ượ ả ậ ể ọ ệ ắ
x p.ế
Hi u các l u đ c a các gi i thu t s p x p.ể ư ồ ủ ả ậ ắ ế
Hi u các ch ng trình s p x p. ể ươ ắ ế
Hi u đ c vi c đánh giá các gi i thu t. ể ượ ệ ả ậ
T m quan tr ng c a bài toán s p x pầ ọ ủ ắ ế
S p x p m t danh sách các đ i t ng theo m t ắ ế ộ ố ượ ộ
th t nào đó là m t bài toán th ng đ c v n ứ ự ộ ườ ượ ậ
d ng trong các ng d ng tin h c.ụ ứ ụ ọ
S p x p là m t yêu c u không th thi u trong ắ ế ộ ầ ể ế
khi thi t k các ph n m m. ế ế ầ ề
Do đó vi c nghiên c u các ph ng pháp s p ệ ứ ươ ắ
x p là r t c n thi t đ v n d ng trong khi l p ế ấ ầ ế ể ậ ụ ậ
trình.
S p x p trong và s p x p ngoàiắ ế ắ ế
S p x p trongắ ế là s s p x p ự ắ ế d li u đ c t ch c trong b nh ữ ệ ượ ổ ứ ộ ớ
trong c a máy tính.ủ
Các đ i t ng c n đ c s p x p là các m u tin g m m t ho c nhi u ố ượ ầ ượ ắ ế ẩ ồ ộ ặ ề
tr ng. M t trong các tr ng đ c g i là khóa (key), ki u c a nó là m t ườ ộ ườ ượ ọ ể ủ ộ
ki u có quan h th t (nh các ki u s nguyên, s th c, chu i ký t ...). ể ệ ứ ự ư ể ố ố ự ỗ ự
Danh sách các đ i t ng c n s p x p s là m t m ng c a các m u tin ố ượ ầ ắ ế ẽ ộ ả ủ ẩ
v a nói trên. ừ ở
M c đích c a vi c s p x p là t ch c l i các m u tin sao cho các khóa ụ ủ ệ ắ ế ổ ứ ạ ẩ
c a chúng đ c s p th t t ng ng v i quy lu t s p x p. ủ ượ ắ ứ ự ươ ứ ớ ậ ắ ế
M t cách m c nhiên, quy lu t s p x p là th t không gi m. Khi c n s p ộ ặ ậ ắ ế ứ ự ả ầ ắ
x p theo th t không tăng thì ph i nói rõ.ế ứ ự ả
S p x p ngoàiắ ế là s s p x p đ c s d ng khi s l ng đ i t ng c n ự ắ ế ượ ử ụ ố ượ ố ượ ầ
s p x p l n không th l u tr trong b nh trong mà ph i l u tr trên ắ ế ớ ể ư ữ ộ ớ ả ư ữ b ộ
nh ngoàiớ .
T ch c d li u và ngôn ng cài đ tổ ứ ữ ệ ữ ặ
Ð trình bày các ví d minh h a chúng ta s dùng C ể ụ ọ ẽ
(Turbo C++, Version 3.0) làm ngôn ng th hi n và ữ ể ệ
s d ng khai báo sau. ử ụ
const int n = 10;
typedef int keytype;
typedef float othertype;
typedef struct recordtype {
keytype key;
othertype otherfields;
};
recordtype a[n]; /* khai bao mang a co n phan tu */
T ch c d li u và ngôn ng cài đ t (tt)ổ ứ ữ ệ ữ ặ
void Swap(recordtype *x, recordtype *y)
{
recordtype temp;
temp = *x;
*x = *y;
*y = temp;
}
C n th y r ng th t c Swap l y O(1) th i gian vì ch ầ ấ ằ ủ ụ ấ ờ ỉ
th c hi n 3 l nh gán n i ti p nhau.ự ệ ệ ố ế
Gi i thu t s p x p ch n (Selection Sort)ả ậ ắ ế ọ
B c 0, ch n ph n t có khóa nh nh t trong n ph n ướ ọ ầ ử ỏ ấ ầ
t t a[0] đ n a[n-1] và hoán v nó v i ph n t a[0].ử ừ ế ị ớ ầ ử
B c 1, ch n ph n t có khóa nh nh t trong n-1 ph n ướ ọ ầ ử ỏ ấ ầ
t t a[1] đ n a[n-1] và hoán v nó v i a[1].ử ừ ế ị ớ
T ng quát b c th i, ch n ph n t có khoá nh ổ ở ướ ứ ọ ầ ử ỏ
nh t trong n-i ph n t t a[i] đ n a[n-1] và hoán v nó ấ ầ ử ừ ế ị
v i a[i].ớ
Sau n-1 b c này thì m ng đã đ c s p x p.ướ ả ượ ắ ế
Ph ng pháp ch n ph n tươ ọ ầ ử
Đ u tiên ta đ t khoá nh nh t là khoá c a a[i] (lowkey ầ ặ ỏ ấ ủ
= a[i].key) và ch s c a ph n t có khoá nh nh t là i ỉ ố ủ ầ ử ỏ ấ
(lowindex = i).
Xét các ph n t a[j] (v i j t i+1 đ n n-1), n u khoá c a ầ ử ớ ừ ế ế ủ
a[j] nh h n khoá nh nh t (a[j].key < lowkey) thì đ t ỏ ơ ỏ ấ ặ
l i l i khoá nh nh t là khoá c a a[j] (lowkey = a[j].key) ạ ạ ỏ ấ ủ
và ch s c a ph n t có khoá nh nh t là j (lowindex ỉ ố ủ ầ ử ỏ ấ
= j).
Khi đã xét h t các a[j] (j>n-1) thì ph n t có khoá nh ế ầ ử ỏ
nh t là a[lowindex]. ấ
Ví d s p x p ch nụ ắ ế ọ
Khóa
Bước
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]
Ban đầu 5 6 2 2 10 12 9 10 9 3
Bước 0 2 6 5 2 10 12 9 10 9 3
Bước 1
2
5 6 10 12 9 10 9 3
Bước 2
3
6 10 12 9 10 9 5
Bước 3
5
10 12 9 10 9 6
Bước 4
6
12 9 10 9 10
Bước 5
9
12 10 9 10
Bước 6
9
10 12 10
Bước 7
10
12 10
Bước 8
10
12
Kết quả 2 2 3 5 6 9 9 10 10 12
L u đ ư ồ
s p x p ch nắ ế ọ
Begin
i = 0
i<=n-2
lowindex = i
lowkey = a[i].key
j<=n-1
i = i+1
a[j].key<lowkey
lowindex = j
lowkey = a[j].key
j = j+1
S
j = i+1
End
swap(a[i],a[lowindex])
S
Đ
S
Đ
Đ
Ch ng trình s p x p ch nươ ắ ế ọ
void SelectionSort(void)
{ int i,j,lowindex;
keytype lowkey;
/*1*/ for (i=0; i<=n-2; i++) {
/*2*/ lowindex = i;
/*3*/ lowkey = a[i].key;
/*4*/ for (j = i+1; j <= n-1; j++)
/*5*/ if (a[j].key < lowkey) {
/*6*/ lowkey = a[j].key;
/*7*/ lowindex = j; }
/*8*/ Swap(&a[i],&a[lowindex]);
}
}
Đánh giá s p x p ch nắ ế ọ
Hàm Swap t n O(1).ố
Toàn b ch ng trình ch bao g m l nh /*1*/. L nh /*1*/ ch a ộ ươ ỉ ồ ệ ệ ứ
các l nh “đ ng c p” /*2*/, /*3*/, /*4*/ và /*8*/, trong đó các ệ ồ ấ
l nh /*2*/, /*3*/ và /*8*/ đ u t n th i gian O(1). ệ ề ố ờ
L nh /*6*/ và /*7*/ đ u t n O(1) nên l nh /*5*/ t n O(1).ệ ề ố ệ ố
Vòng l p /*4*/ th c hi n n-i-1 l n, vì j ch y t i+1 đ n n-1, m i ặ ự ệ ầ ạ ừ ế ỗ
l n l y O(1), nên l y O(n-i-1) th i gian. ầ ấ ấ ờ
G i T(n) là th i gian th c hi n c a ch ng trình, thì T(n) là th i ọ ờ ự ệ ủ ươ ờ
gian th c hi n l nh /*1*/. Mà l nh /*1*/ có i ch y t 0 đ n n-2 ự ệ ệ ệ ạ ừ ế
nên ta có:
)O(n
2
1)-n(n
1)-i-(nT(n)
2
2-n
0=i
===
∑
Gi i thu t s p x p xen (Insertion ả ậ ắ ế
Sort)
Tr c h t ta xem ph n t a[0] là m t dãy đã có th t .ướ ế ầ ử ộ ứ ự
B c 1, xen ph n t a[1] vào danh sách đã có th t ướ ầ ử ứ ự
a[0] sao cho a[0], a[1] là m t danh sách có th t .ộ ứ ự
B c 2, xen ph n t a[2] vào danh sách đã có th t ướ ầ ử ứ ự
a[0], a[1] sao cho a[0], a[1], a[2] là m t danh sách có th ộ ứ
t .ự
T ng quát, b c i, xen ph n t a[i] vào danh sách đã có ổ ướ ầ ử
th t a[0], a[1], … a[i-1] sao cho a[0], a[1],.. a[i] là m t ứ ự ộ
danh sách có th t .ứ ự
Sau n-1 b c thì k t thúc.ướ ế
Ph ng pháp xenươ
Ph n t đang xét a[j] s đ c xen vào v trí thích ầ ử ẽ ượ ị
h p trong danh sách các ph n t đã đ c s p tr c ợ ầ ử ượ ắ ướ
đó a[0],a[1],..a[j-1]:
So sánh khoá c a a[j] v i khoá c a a[j-1] đ ng ngay ủ ớ ủ ứ
tr c nó. ướ
N u khoá c a a[j] nh h n khoá c a a[j-1] thì hoán ế ủ ỏ ơ ủ
đ i a[j-1] và a[j] cho nhau và ti p t c so sánh khoá ổ ế ụ
c a a[j-1] (lúc này a[j-1] ch a n i dung c a a[j]) v i ủ ứ ộ ủ ớ
khoá c a a[j-2] đ ng ngay tr c nó... ủ ứ ướ
Ví d s p x p xenụ ắ ế
Khóa
Bước
a[0] a[1] a[2] a[3] a[4] a[5] a[6] A[7] a[8] a[9]
Ban đầu 5 6 2 2 10 12 9 10 9 3
Bước 1
5 6
Bước 2
2 5 6
Bước 3
2 2 5 6
Bước 4
2 2 5 6 10
Bước 5
2 2 5 6 10 12
Bước 6
2 2 5 6 9 10 12
Bước 7
2 2 5 6 9 10 10 12
Bước 8
2 2 5 6 9 9 10 10 12
Bước 9
2 2 3 5 6 9 9 10 10 12
L u đ ư ồ
s p x p xenắ ế
Begin
i = 1
i<=n-1
(j>0) and
(a[j].key < a[j-1].key)
i = i+1
j = i
End
swap(a[j],a[j-1])
j = j-1
S
Đ
Đ
S
Ch ng trình s p x p xen ươ ắ ế
void InsertionSort(void)
{
int i,j;
/*1*/ for (i = 1; i<= n-1; i++) {
/*2*/ j = i;
/*3*/ while ((j>0) && (a[j].key < a[j-1].key)) {
/*4*/ Swap(&a[j], &a[j-1]);
/*5*/ j= j-1;
}
}
}
Đánh giá s p x p xenắ ế
Các l nh /*4*/ và /*5*/ đ u l y O(1). Vòng l p ệ ề ấ ặ
/*3*/, trong tr ng h p x u nh t, ch y i l n (j ườ ợ ấ ấ ạ ầ
gi m t i đ n 1), m i l n t n O(1) nên /*3*/ l y i ả ừ ế ỗ ầ ố ấ
th i gian. ờ
L nh /*2*/ và /*3*/ là hai l nh n i ti p nhau, l nh ệ ệ ố ế ệ
/*2*/ l y O(1) nên c hai l nh này l y i.ấ ả ệ ấ
Vòng l p /*1*/ có i ch y t 1 đ n n-1 nên ta có:ặ ạ ừ ế
)O(n
2
1)-n(n
iT(n)
2
1-n
1i
===
∑
=
Gi i thu t s p x p “n i b t” (Bubble ả ậ ắ ế ổ ọ
Sort)
B c 1: Xét các ph n t a[j] (j gi m t n-1 đ n 1), ướ ầ ử ả ừ ế
so sánh khoá c a a[j] v i khoá c a a[j-1]. N u khoá ủ ớ ủ ế
c a a[j] nh h n khoá c a a[j-1] thì hoán đ i a[j] và ủ ỏ ơ ủ ổ
a[j-1] cho nhau. Sau b c này thì a[0] có khoá nh ướ ỏ
nh t.ấ
B c 2: Xét các ph n t a[j] (j gi m t n-1 đ n 2), ướ ầ ử ả ừ ế
so sánh khoá c a a[j] v i khoá c a a[j-1]. N u khoá ủ ớ ủ ế
c a a[j] nh h n khoá c a a[j-1] thì hoán đ i a[j] và ủ ỏ ơ ủ ổ
a[j-1] cho nhau. Sau b c này thì a[1] có khoá nh ướ ỏ
th 2.ứ
…
Sau n-1 b c thì k t thúc.ướ ế
Ví d s p x p “n i b t”ụ ắ ế ổ ọ
Khóa
Bước
a[0] a[1] a[2] a[3] a[4] A[5] a[6] a[7] a[8] a[9]
Ban đầu 5 6 2 2 10 12 9 10 9 3
Bước 1
2
5 6 2 3 10 12 9 10 9
Bước 2
2
5 6 3 9 10 12 9 10
Bước 3
3
5 6 9 9 10 12 10
Bước 4
5
6 9 9 10 10 12
Bước 5
6
9 9 10 10 12
Bước 6
9
9 10 10 12
Bước 7
9
10 10 12
Bước 8
10
10 12
Bước 9
10
12
Kết quả 2 2 3 5 6 9 9 10 10 12
L u đ ư ồ
s p x p n i b tắ ế ổ ọ
Begin
i = 0
i<=n-2
i = i+1
j = n-1
End
swap(a[j],a[j-1])
S
Đ
Đ
S
a[j].key < a[j-1].key
j>= i+1
Đ
j = j-1
S
Ch ng trình ươ
s p x p “n i ắ ế ổ
b t”ọ
void BubbleSort(void)
{ int i,j;
/*1*/ for(i= 0; i<= n-2; i++)
/*2*/ for(j=n-1;j>=i+1; j--)
/*3*/ if (a[j].key < a[j-1].key)
/*4*/ Swap(&a[j],&a[j-1]);
}
Begin
i = 0
i<=n-2
i = i+1
j = n-1
End
swap(a[j],a[j-1])
S
Đ
Đ
S
a[j].key < a[j-1].key
j>=
i+1
Đ
j = j-1
S
Ý t ng c a QuickSortưở ủ
Ch n m t giá tr khóa v làm ch t (pivot).ọ ộ ị ố
Phân ho ch dãy a[0]..a[n-1] thành hai m ng con "bên trái" và ạ ả
"bên ph i". M ng con "bên trái" bao g m các ph n t có ả ả ồ ầ ử khóa
nh h n ch tỏ ơ ố , m ng con "bên ph i" bao g m các ph n t có ả ả ồ ầ ử
khóa l n h n ho c b ng ch tớ ơ ặ ằ ố .
S p x p m ng con “bên trái” và m ng con “bên ph i”.ắ ế ả ả ả
Sau khi đã s p x p đ c m ng con “bên trái” và m ng con ắ ế ượ ả ả
“bên ph i” thì m ng đã cho s đ c s p b i vì t t c các khóa ả ả ẽ ượ ắ ở ấ ả
trong m ng con “bên trái” đ u nh h n các khóa trong m ng ả ề ỏ ơ ả
con “bên ph i”.ả
Vi c s p x p các m ng con “bên trái” và “bên ph i” cũng đ c ệ ắ ế ả ả ượ
ti n hành b ng ph ng pháp nói trên.ế ằ ươ
M t m ng ch g m m t ph n t ho c g m nhi u ph n t có ộ ả ỉ ồ ộ ầ ử ặ ồ ề ầ ử
khóa b ng nhau thì đã có th t . ằ ứ ự
Ph ng pháp ch n ch tươ ọ ố
Ch n giá tr ọ ị khóa l n nh tớ ấ trong hai ph n t có khóa ầ ử
khác nhau đ u tiên k t trái qua. ầ ể ừ
N u m ng ch g m m t ph n t hay g m nhi u ph n ế ả ỉ ồ ộ ầ ử ồ ề ầ
t có khóa b ng nhau thì không cóử ằ ch tố .
Ví d :ụ Ch n ch t trong các m ng sauọ ố ả
–
Cho m ng g m các ph n t có khoá là 6, 6, 5, 8, 7, 4, ta ch n ả ồ ầ ử ọ
ch t là 6 (khoá c a ph n t đ u tiên).ố ủ ầ ử ầ
–
Cho m ng g m các ph n t có khoá là 6, 6, 7, 5, 7, 4, ta ch n ả ồ ầ ử ọ
ch t là 7 (khoá c a ph n t th 3).ố ủ ầ ử ứ
–
Cho m ng g m các ph n t có khoá là 6, 6, 6, 6, 6, 6 thì không ả ồ ầ ử
có ch t (các ph n t có khoá b ng nhau).ố ầ ử ằ
–
Cho m ng g m m t ph n t có khoá là 6 thì không có ch t (do ả ồ ộ ầ ử ố
ch có m t ph n t ). ỉ ộ ầ ử
Ph ng pháp phân ho chươ ạ
Ð phân ho ch m ng ta dùng 2 "con nháy" L và R trong ể ạ ả
đó L t bên trái và R t bên ph i.ừ ừ ả
Ta cho L ch y sang ph i cho t i khi g p ph n t có khóa ≥ ạ ả ớ ặ ầ ử
ch t ố
Cho R ch y sang trái cho t i khi g p ph n t có khóa < ạ ớ ặ ầ ử
ch t. ố
T i ch d ng c a L và R n u L < R thì hoán v a[L],a[R]. ạ ỗ ừ ủ ế ị
L p l i quá trình d ch sang ph i, sang trái c a 2 "con ặ ạ ị ả ủ
nháy" L và R cho đ n khi L > R. ế
Khi đó L s là đi m phân ho ch, c th là a[L] là ph n t ẽ ể ạ ụ ể ầ ử
đ u tiên c a m ng con “bên ph i”.ầ ủ ả ả