You are on page 1of 62

Chương 6

Sắp xếp

LOGO
Nội dung

1. Bài toán sắp xếp


2. Một số phương pháp sắp xếp đơn giản
2.1. Sắp xếp kiểu lựa chọn (Selection sort)
2.2. Sắp xếp kiểu thêm dần (Insertion sort)
2.3. Sắp xếp kiểu đổi chỗ (Exchange sort)
2.4. Phân tích và so sánh ba phương pháp
3. Sắp xếp nhanh (Quick sort)
4. Sắp xếp theo kiểu hòa nhập (Merge-sort)
Bài toán sắp xếp
 Cho danh sách có n phần tử a0, a1, a2…, an-1.
 Sắp xếp là quá trình xử lý các phần tử trong
danh sách để đặt chúng theo một thứ tự thỏa
mãn một số tiêu chuẩn nào đó, như:
 Sắp xếp danh sách lớp học tăng theo điểm trung
bình.
 Sắp xếp danh sách sinh viên tăng theo tên.
 …
 Để đơn giản trong việc trình bày giải thuật ta
dùng mảng 1 chiều a để lưu danh sách trên
trong bộ nhớ chính.
Bài toán sắp xếp
 a: là dãy các phần tử dữ liệu
 Để sắp xếp dãy a theo thứ tự (thứ tự tăng),
ta tiến hành triệt tiêu tất cả các nghịch thế
Nghịch thế:
• Cho dãy có n phần tử a0, a1,…,an-1
• Nếu i<j và ai >aj
34 3 4 8 a[0], a[1] là cặp nghịch thế

 Đánh giá độ phức tạp của giải thuật, ta tính


Css: Số lượng phép so sánh cần thực hiện
CHV: Số lượng phép hoán vị cần thực hiện
Sắp xếp kiểu lựa chọn
(Selection sort)
 Ý tưởng:

 Chọn phần tử nhỏ nhất trong n phần tử trong


dãy hiện hành ban đầu.
 Đưa phần tử này về vị trí đầ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 hiện hành 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ử
Các bước của thuật toán chọn
trực tếp
 Bước 1: i = 0;
 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 : Đổi chỗ a[min] và a[i]
 Bước 4 : Nếu i<n-1 thì
i = i+1;
Lặp lại Bước 2;
Ngược lại: Dừng.
Sắp xếp kiểu lựa chọn
(Selection sort)

Cho dãy số a:
12 2 8 5 1 6 4 15
Sắp xếp kiểu lựa chọn
(Selection sort)

i=0

i=1
Sắp xếp kiểu lựa chọn
(Selection sort)

i=2

i=3

i=4
Sắp xếp kiểu lựa chọn
(Selection sort)

i=5

i=6
Ví dụ
Dãy: 45 27 75 15 65 58 94 37 99 87
i 0 1 2 3 4 5 6 7 8 9
Ban 45 27 75 15 65 58 94 37 99 87
đầu
Lượt
1 15 27 75 45 65 58 94 37 99 87
2 15 27 75 45 65 58 94 37 99 87
3 15 27 37 45 65 58 94 75 99 87
4 15 27 37 45 65 58 94 75 99 87
5 15 27 37 45 58 65 94 75 99 87
6 15 27 37 45 58 65 94 75 99 87
7 15 27 37 45 58 65 75 94 99 87
8 15 27 37 45 58 65 75 87 99 94
9 15 27 37 45 58 65 75 87 94 99
Sắp xếp kiểu lựa chọn
(Selection sort)
Giải thuật:
SELECT_SORT(K, n) {
for (i = 0; i< n-1; i++) {
m = i;
for (j = i+1; j < n; j++)
if (K[j] < K[m]) m = j;
if (i < m) {
x = K[i];
K[i] = K[m];
K[m] = x;
}
}
}
Sắp xếp kiểu thêm dần
(Insertion sort)
Giả sử có một dãy a0 , a1 ,... ,an-1 trong
đó i phần tử đầu tiên a0 , a1 ,... ,ai-1 đã có
thứ tự.

Tìm cách chèn phần tử ai vào vị trí thích


hợp của đoạn đã được sắp để có dãy mới
a0 , a1,... ,ai trở nên có thứ tự. Vị trí này
chính là vị trí giữa hai phần tử ak-1 và ak
thỏa ak-1 < ai < ak (1≤k≤i).
Sắp xếp kiểu thêm dần
(Insertion sort)
Bước 1: i = 1; //giả sử có đoạn a[1]
Bước 2: x = a[i]; Tìm vị trí pos thích hợp
trong đoạn a[1] đến a[i-1] để chèn a[i]
Bước 3: Dời các phần tử từ a[pos] đến
a[i-1] sang phải 1 vị trí để chổ cho a[i]
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
Sắp xếp kiểu thêm dần
(Insertion sort)

 Cho dãy số :
12 2 8 5 1 6 4 15

i=1

i=2
Sắp xếp kiểu thêm dần
(Insertion sort)

i=3

i=4

i=5
Sắp xếp kiểu thêm dần
(Insertion sort)

i=6

i=7
Ví dụ
Dãy: 45 27 75 15 65 58 94 37 99 87
i 0 1 2 3 4 5 6 7 8 9
Ban 45 27 75 15 65 58 94 37 99 87
đầu
Lượt
1 27 45 - - - - - - - -
2 27 45 75 - - - - - - -
3 15 27 45 75 - - - - - -
4 15 27 45 65 75 - - - - -
5 15 27 45 58 65 75 - - - -
6 15 27 45 58 65 75 94 - - -
7 15 27 37 45 58 65 75 94 - -
8 15 27 37 45 58 65 75 94 99 -
9 15 27 37 45 58 65 75 87 94 99
Sắp xếp kiểu thêm dần
(Insertion sort)

Giải thuật
INSERT_SORT (K, n) {/* x: biến phụ chứa khoá mới đang xét*/
for (i = 1; i< n; i++) {
x = K[i];
j = i-1;
while ((K[j] > x) && (j>=0)) {//Lùi K[j] một vị trí
K[j+1] = K[j];
j--;
}
K[j+1] = x;
}
}
Sắp xếp kiểu đổi chỗ
(Exchange sort)
Ý tưởng:

 Xuất phát từ cuối dãy, đổi chỗ các cặp phần


tử kế cận để đưa phần tử nhỏ hơn trong cặp
phần tử đó về vị trí đúng đầu dãy hiện hành,
sau đó sẽ không xét đến nó ở bước tiếp theo,
do vậy ở 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.
Sắp xếp kiểu đổi chỗ
(Exchange sort)
Bước 1 : i = 0; // lần xử lý đầu tiên
Bước 2 : j = n-1;//Duyệt từ cuối dãy về i
Trong khi (j>i) thực hiện:
Nếu a[j]<a[j-1]
Doicho(a[j],a[j-1]);
j = j-1;
Bước 3 : i = i+1; // lần xử lý kế tiếp
Nếu i =n: Hết dãy. Dừng
Ngược lại: Lặp lại Bước 2.
Sắp xếp kiểu đổi chỗ
(Exchange sort)
Cho dãy số a:
2 12 8 5 1 6 4 15

i=0 j=6

i=0 i=4
Sắp xếp kiểu đổ chỗ
(Exchange sort)

i=0 j=3

i=0 j=2

i=0 j=1
Sắp xếp kiểu đổi chỗ
(Exchange sort)

i=1 j=5

i=1 j=4

i=1 j=3
Sắp xếp kiểu đổi chỗ
(Exchange sort)

i=2 j=5

i=2 j=4

i=3 j=6
Sắp xếp kiểu đổi chỗ
(Exchange sort)

i=3 j=6

i=4 j=6

i=5
Ví dụ
Dãy: 45 27 75 15 65 58 94 37 99 87
i 0 1 2 3 4 5 6 7 8 9
Ban 45 27 75 15 65 58 94 37 99 87
đầu
Lượt
1 15 45 27 75 37 65 58 94 87 99
2 15 27 45 37 75 58 65 87 94 99
3 15 27 37 45 58 75 65 87 94 99
4 15 27 37 45 58 65 75 87 94 99
5 15 27 37 45 58 65 75 87 94 99
6 15 27 37 45 58 65 75 87 94 99
7 15 27 37 45 58 65 75 87 94 99
8 15 27 37 45 58 65 75 87 94 99
9 15 27 37 45 58 65 75 87 94 99
Sắp xếp kiểu đổi chỗ
(Exchange sort)
Giải thuật:
BUBLE_SORT (K, n) {
for (i = 0; i< n-1; i++)
for (j = n-1; j>i; j--)
if (K[j] < K[j-1])
{
x = K[j];
K[j] = K[j – 1] ;
K[j – 1] = x
}
}
Độ phức tạp của thuật toán
Sắp xếp kiểu lựa chọn
Độ phức tạp của thuật toán
Sắp xếp kiểu thêm dần
Độ phức tạp của thuật toán
Sắp xếp kiểu đổi chỗ
Săp xếp nhanh (Quick sort)

Ý tưởng:
 sắp xếp dãy a1, a2 ..., an dựa trên việc phân hoạch
dãy ban đầu thành 3 phần :

• Phần 1: Gồm các phần tử có giá trị bé hơn x


• Phần 2: Gồm các phần tử có giá trị bằng x
• Phần 3: Gồm các phần tử có giá trị lớn hơn x
với x là giá trị của một phần tử tùy ý trong dãy ban
đầu.
Săp xếp nhanh (Ý tưởng)

 Sau khi thực hiện phân hoạch, dãy ban đầu được
phân thành 3 đoạn:

• 1. ak ≤ x , với k = 1 .. j
• 2. ak = x , với k = j+1 .. i-1
• 3. ak  x , với k = i..n
Săp xếp nhanh (Ý tưởng)

Đoạn thứ 2 đã có thứ tự.


 Nếu các đoạn 1 và 3 chỉ có 1 phần tử: đã có
thứ tự
 khi đó dãy con ban đầu đã được sắp
xếp.
Săp xếp nhanh (Ý tưởng)

Đoạn thứ 2 đã có thứ tự.


 Nếu các đoạn 1 và 3 có nhiều hơn 1 phần tử
thì dãy ban đầu chỉ có thứ tự khi các đoạn 1,
3 được sắp xếp.
 Để sắp xếp các đoạn 1 và 3, ta lần lượt tiến
hành việc phân hoạch từng dãy con theo
cùng phương pháp phân hoạch dãy ban đầu
vừa trình bày …
Săp xếp nhanh

 Bước 1: Chọn tùy ý một phần tử a[k] trong dãy là


giá trị mốc (l≤k≤ r):
x = a[k]; i = l; j = r;
 Bước 2: Phát hiện và hiệu chỉnh cặp phần tử
a[i], a[j] nằm sai chỗ:
• Bước 2a: Trong khi (a[i]<x) i++;
• Bước 2b: Trong khi (a[j]>x) j--;
• Bước 2c: Nếu i<j Swap(a[i],a[j]);
 Bước 3: Nếu i< j: Lặp lại Bước 2.
Ngược lại: Dừng
Săp xếp nhanh – Ví dụ

 Cho dãy số a:
12 2 8 5 1 6 4 15

Phân hoạch đoạn l =0, r = 7: x = a[3] = 5


Săp xếp nhanh – Ví dụ
Săp xếp nhanh – Ví dụ

Phân hoạch đoạn l = 0, r = 2:


Săp xếp nhanh – Ví dụ

Phân hoạch đoạn l =4, r = 7:


Săp xếp nhanh – Ví dụ

Phân hoạch đoạn l =6, r = 7:


Ví dụ
Dãy: 45 27 75 15 65 58 94 37 99 87
i 0 1 2 3 4 5 6 7 8 9
Ban 45 27 75 15 65 58 94 37 99 87
đầu
Lượt
1 (45 27 37 15 58) 65 (94 75 99 87)
2 (15 27) 37 (45 58) 65 (94 75 99 87)
3 15 (27) 37 (45 58) 65 (94 75 99 87)
4 15 27 37 (45 58) 65 (94 75 99 87)
5 15 27 37 45 (58) 65 (75 87 94 99)
6 15 27 37 45 58 65 75 (94 99 87)
7 15 27 37 45 58 65 75 (87) 94 (99)
8 15 27 37 45 58 65 75 87 94 (99)
9 15 27 37 45 58 65 75 87 94 99
Săp xếp nhanh - Giải thuật
QuickSort(a, left, right)
{
x = a[(left+right)/2];
i = left; j = right;
do{
while(a[i]< x) i++;
while(a[j]> x) j--;
if(i<= j){
Swap(a[i],a[j]);
i++ ; j--;
}
} while(i<=j);
if(left<j)
QuickSort(a, left, j);
if(i<right)
QuickSort(a, i, right);
}
Độ phức tạp của thuật toán
Sắp xếp nhanh
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
Ý tưởng:
 Mỗi dãy a1, a2, ..., an bất kỳ là một tập hợp
các dãy con liên tiếp mà mỗi dãy con đều đã
có thứ tự.
• Ví dụ: dãy 12, 2, 8, 5, 1, 6, 4, 15 có thể coi như
gồm 5 dãy con không giảm (12); (2, 8); (5); (1, 6);
(4, 15).
 Dãy đã có thứ tự coi như có 1 dãy con.
Hướng tiếp cận: tìm cách làm giảm
số dãy con không giảm của dãy ban
đầu.
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 Bước 1 : // Chuẩn bị
k = 1; // k là chiều dài của dãy con hiện hành
 Bước 2 :
Tách dãy a0, a1, ., an-1 thành 2 dãy b, c theo nguyên
tắc luân phiên từng nhóm k phần tử:
b = a0, ., ak, a2k, ., a3k, .
c = ak+1, ., a2k+1, a3k+1, .
 Bước 3 :
Trộn từng cặp dãy con gồm k phần tử của 2
dãy b, c vào a.
 Bước 4 :
k = k*2;
Nếu k < n thì trở lại bước 2.
Ngược lại: Dừng
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 k = 1: Phân phối luân phiên
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 k=1: Trộn từng cặp đường chạy
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 k=2: Phân phối luân phiên
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 k=2: Trộn từng cặp đường chạy
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 k = 4: Phân phối luân phiên
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 k=4: Trộn từng cặp đường chạy
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
k=8

0 1 2 3 4 5 6 7

1 2 4 5 6 8 12 15
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)

1 2 3 4 5 6 7 8

1 2 4 5 6 8 12 15
Ví dụ
Dãy: 45 27 75 15 65 58 94 37 99 87

i 0 1 2 3 4 5 6 7 8 9
Ban 45 27 75 15 65 58 94 37 99 87
đầu
Lượt
1 [45] [27] [75] [15] [65] [58] [94] [37] [99] [87]
2 [27 45] [15 75] [58 65] [37 94] [87 99]
3 [15 27 45 75] [37 58 65 94] [87 99]
4 [15 37 27 45 58 65 75 94] [87 99]
5 [15 37 27 45 58 65 75 87 94 99]
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 Giải thuật:
MERGE (K, b, m, n, X){/*thực hiện hoà nhập hai mảng con đã
được sắp xếp thành một mảng mới X được sắp xếp*/
i = t = b; j = m + 1;
while (i <= m) and (j <= n) //hai mảng con vẫn còn khoá
if (K[i] < K[j]) // So sánh để chọn khoá nhỏ hơn
X[t++] = K[i++];
else
X[t++] = K[j++];
// Một trong hai mảng con đã hết khoá trước
if (i > m) // Mảng 1 hết khoá trước
for (; j<=n; )
X[t++] = K[j++];
else // Mảng 2 hết khoá trước
for (; i<=m; )
X[t++] = K[i++];}
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 Giải thuật:
MPASS (K, X, n, h) {/*thực hiện một bước của sắp xếp kiểu hoà
nhập. Nó hoà nhập từng cặp mạch kế cận nhau, có độ dài h từ mảng K
sang mảng X, n là số lượng khoá trong K */
i = 0;
while (i<= n-2*h) //Hoà nhập cặp mạch có độ dài h
{
MERGE (K, i, i+h–1, i+2*h–1, X);
i = i+2*h;
}
if (i + h < n) //Hoà nhập cặp mạch còn lại với tổng độ dài < 2*h
MERGE (K, i, i+h–1, n-1, X);
else // Chỉ còn một mạch
for (; i<n; i++)
X[i] = K[i];
}
Thuật toán sắp xếp kiểu hòa
nhập (Merge sort)
 Giải thuật:
STRAIGHT_MSORT (K, n) {/* Để thực hiện lưu trữ các mạch mới,
khi hoà nhập, ở đây phải dùng một mảng phụ X[n], K và X sẽ được dùng
luân phiên, h ghi nhận kích thước của các mạch, sau mỗi lượt h được
tăng gấp đôi */
h = 1;
while (h < n)
{
MPASS (K, X, n , h); // Hoà nhập và chuyển các khoá vào X
MPASS (X, K, n , 2*h); // Hoà nhập và chuyển các khoá vào K
h = 4+h;
}
}
Thuật toán sắp xếp kiểu hòa nhập

hàm MPASS: O(n)


số lượt gọi MPASS trong giải thuật
STRAIGHT_MSORT là [log2n]
sắp xếp kiểu hoà nhập hai đường trực tiếp
có cấp thời gian là O[nlog2n].
nhược điểm: chi phí về không gian khá lớn.
Nó đòi hỏi tới 2n phần tử nhớ, gấp đôi so
với các phương pháp thông thường
=> thường sử dụng khi sắp xếp ngoài, đối với
các tệp.
Nhận xét
 Các phương pháp sắp xếp đơn giản đã thể hiện ba
kỹ thuật cơ sở của sắp xếp (dựa vào phép so sánh
giá trị khoá), cấp độ lớn của thời gian thực hiện
chung là O(n2), vì vậy chỉ nên sử dụng khi n nhỏ.
 giải thuật cải tiến như QUICK_SORT đã đạt được
hiệu quả cao (có cấp độ lớn của thời gian thực hiện
là O[nlog2n]), nên thường được sử dụng khi n lớn.
 MERGE_SORT không kém hiệu lực về thời gian thực
hiện nhưng về không gian thì không thích nghi với
sắp xếp trong.
 Nếu bảng cần sắp xếp vốn có khuynh hướng hầu
như “đã được sắp sẵn” thì QUICK_SORT lại không
nên dùng.
Q&A
Bài tập áp dụng
1. Cho dãy khóa:
97 15 27 45 21 59 62 83 25 65
Hãy minh hoạ quá trình thực hiện các phương
pháp sắp xếp đã học đối với dãy khoá này
theo thứ tự tăng dần, giảm dần.
2. Hãy sửa lại ba giải thuật sắp xếp đơn giản
để thực hiện sắp xếp theo thứ tự giảm dần.
3. Có thể phát triển phép hoà nhập hai đường
để thực hiện hoà nhập k đường được không
(k > 2).

You might also like