Chương 5: Sắp xếp - Cấu trúc dữ liệu và giải thuật (ET2100) | Trường Đại học Bách khoa Hà Nội

Sắp xếp (Sorting) là quá trình tổ chức lại họ các dữ liệu theo thứ tự giảm dần hoặc tăng dần.

lOMoARcPSD| 27879799
1
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
Cấu trúc dữ liệu và thuật toán
Nguyễn Khánh Phương
Computer Science department
School of Informaon and Communicaon technology
E-mail: phuongnk@soict.hust.edu.vn
Nội dung khóa học
Chương 1. Các khái niệm cơ bản
Chương 2. Các sơ ồ thuật toán
Chương 3. Các cấu trúc dữ liệu cơ bản
Chương 4. Cây
Chương 5. Sắp xếp
Chương 6. Tìm kiếm
Chương 7. Đồ th
2
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
lOMoARcPSD| 27879799
2
Chương 5. Sắp xếp
Nguyễn Khánh Phương
Computer Science department
School of Informaon and Communicaon technology
E-mail: phuongnk@soict.hust.edu.vn
Bài toán sắp xếp
Sắp xếp (Sorng) là quá trình tổ chức lại họ các dữ liệu theo thứ tự giảm dần
hoặc tăng dần.
Dữ liệu cần sắp xếp có thể là:
Số nguyên/thực.. (integers/oat)
Xâu kí tự (character strings)
Khóa sắp xếp (sort key)
Là bộ phận của bản ghi xác ịnh thứ tự sắp xếp của bản ghi trong họ các bản
ghi.
Ta cần sắp xếp các bản ghi theo thứ tự của các khoá. – Ví dụ: khóa là tong =
toan + ly + hoa
typedef struct{ char *ma; struct{ oat toan, ly, hoa,
tong;
} DT; }thisinh;
typedef struct node{ thisinh data;
struct node* next; 4
}node;
Các loại thuật toán sắp xếp
lOMoARcPSD| 27879799
3
Sắp xếp trong (internal sort):
Đòi hỏi họ dữ liệu ược ưa toàn bộ vào bộ nhớ trong của máy nh
Ví dụ:
inseron sort (sắp xếp chèn), selecon sort (sắp xếp lựa chọn), bubble sort (sắp xếp nổi bọt)
quick sort (sắp xếp nhanh), merge sort (sắp xếp trộn), heap sort (sắp xếp vun ống), sample
sort (sắp xếp da mẫu), shell sort (vỏ sò) Sắp xếp ngoài (external sort):
Họ dữ liệu không thể cùng lúc ưa toàn bộ vào bộ nhớ trong, nhưng có thể ọc vào từng bphận từ
bộ nhớ ngoài
Ví dụ:Poly-phase mergesort (trộn nhiều oạn), cascade-merge (thác nước), oscillang sort (dao
ộng)
Sắp xếp song song (Parallel sort):
Bitonic sort, Batcher even-odd sort.
Smooth sort, cube sort, column sort.
GPU sort.
5
Các ặc trưng của một thuật toán sắp xếp
Tại chỗ (in place): nếu không gian nhph thuật toán òi hỏi O(1), nghĩa b
chặn bởi hằng số không phụ thuộc vào ộ dài của dãy cần sắp xếp.
n ịnh (stable): Nếu các phần tử có cùng giá trvẫn giữ nguyên thứ tự tương ối của
chúng như trước khi sắp xếp.
Bài toán sắp xếp
lOMoARcPSD| 27879799
4
Có hai phép toán cơ bản mà thuật toán sắp xếp thường phải sử dụng:
Đổi chỗ (Swap): Thời gian thực hiện là O(1) void swap( datatype *a, datatype
*b){ datatype *temp = *a; //datatype-kiểu dữ liệu của phần tử
*a = *b;
*b = *temp;
}
So sánh: Compare(a, b) trả lại true nếu a i trước b trong thứ tự cần sắp xếp và
false nếu trái li.
Phân ch thuật toán sắp xếp: thông thường, các thuật toán sẽ sử dụng phép
toán so sánh ể xác ịnh thứ tự giữa hai phần tử rồi thực hiện ổi chỗ nếu
cần. Khi phân ch thuật toán sắp xếp, ta sẽ chỉ cần ếm số phép toán so sánh và số
lần dịch chuyển các phần tử (bỏ qua các phép toán khác không ảnh hưởng ến
kết qu).
7
Bài toán sắp xếp
Các thuật toán chỉ sử dụng phép toán so sánh ể xác ịnh thứ tự giữa hai
phần tử ược gọi là thuật toán sử dụng phép so sánh (Comparison-based sorng
algorithm).
Nếu có những thông n bổ sung về dữ liệu ầu vào, ví dụ như:
Các số nguyên nằm trong khoảng [0..k] trong ó k = O(n)
Các số thực phân b ều trong khoảng [0, 1) ta sẽ có thuật toán
tốt hơn thuật toán sắp xếp chỉ dựa vào phép so sánh.
(Thuật toán thời gian tuyến nh: sắp xếp ếm (coung-sort), sắp xếp theo cơ số
(radixsort), sắp xếp óng gói (bucket-sort))
8
Các thuật toán sắp xếp
lOMoARcPSD| 27879799
5
Khi so sánh các thuật toán, thông thường quan tâm ến:
Thời gian chy. Đối với các dữ liệu rt lớn, các thuật toán không hiệu quả
sẽ chạy rất chậm và không thể ứng dụng trong thực tế.
Bộ nh. Các thuật toán nhanh òi hỏi quy sẽ có thể phải tạo ra các bản
copy của dữ liệu ang xử lí. Với những hệ thống mà bộ nhớ có giới hạn (ví
dụ embedded system), một vài thuật toán sẽ không thể chy ược.
Độ ổn nh (stability). Độ ổn ịnh ược ịnh nghĩa dựa trên iều gì sẽ xảy ra với
các phần tử có giá trị giống nhau.
Đối với thuật toán sắp xếp n ịnh, các phần tử với giá trị bằng nhau sẽ
giữ nguyên thứ tự trong mảng trước và sau khi sắp xếp.
Đối với thuật toán sắp xếp không ổn ịnh, các phần tử có giá trị bằng
nhau sẽ có thể có thứ tự bất k.
9
Tiêu chí lựa chọn giải thuật
Nhiều yếu tố ảnh hưởng:
Ổn nh
Danh sách liên kết hay mảng •
Đặc trưng của dữ liệu cần sắp xếp:
Nhiều khóa ?
Các khóa là phân biệt ?
Nhiều dạng khóa ?
Kích thước bản ghi lớn hay nhỏ ?
Dữ liệu ược sắp xếp ngẫu nhiên?
Không thể bao phủ tất cả các yếu t
Nội dung
lOMoARcPSD| 27879799
6
1. Sắp xếp chèn (Inseron sort)
2. Sắp xếp chọn (Selecon sort)
3. Sắp xếp nổi bọt (Bubble sort)
4. Sắp xếp trộn (Merge sort)
5. Sắp xếp nhanh (Quick sort)
6. Sắp xếp vun ống (Heap sort)
1. Sắp xếp chèn (Inseron sort)
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một con bài vào
bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó bởi việc
dịch chuyển đầu ên là 36 và sau đó là 24.
12
1. Sắp xếp chèn (Inseron sort)
lOMoARcPSD| 27879799
7
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một
con bài vào bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó
bởi việc dịch chuyển đầu ên là 36
và sau đó là 24.
13
1. Sắp xếp chèn (Inseron sort)
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một
con bài vào bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó
bởi việc dịch chuyển đầu ên là 36
và sau đó là 24.
14
1. Sắp xếp chèn (Inseron sort)
lOMoARcPSD| 27879799
8
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một con
bài vào b bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó bởi
việc dịch chuyển đầu ên là 36 và sau
đó là 24.
15
1. Sắp xếp chèn (Inseron sort)
Thuật toán:
Mảng cần sắp xếp ược chia m 2 phần, sorted unsorted: – Những phần
tử nằm trong phần sorted: ã ược sắp xếp
Những phần tử nằm trong phần unsorted: chưa ược sắp xếp
Mỗi bước lặp: phần tử ầu ên thuộc phần unsorted sẽ ược chuyển sang
phần sorted.
Mảng có n phần tử sẽ cần n-1 bước lặp ể sắp xếp xong
16
lOMoARcPSD| 27879799
9
n-
k
úng vị trí trong dãy gồm
k
Dịch tất cả các phần tử a[pos]… a[k-1] sang phi 1 vị trí
n-
k
úng vị trí trong dãy gồm
Tại mỗi ớc lặp
, thể cần nhiều hơn một lần hoán đổi vị trí các phần tử để thể đưa phần tử th
về đúng vị trí của trong dãy cần sắp xếp
k
lOMoARcPSD| 27879799
10
lOMoARcPSD| 27879799
11
Cài ặt: Inseron Sort Algorithm
NGUYỄN KHÁNH PHƯƠNG 21
KHMT – SOICT - ĐHBK HN
Đánh giá phức tạp nh toán của Inseron sort: O(n
2
)
Sắp xếp chèn là tại chỗ và ổn ịnh (In place and Stable)
Phân ch thời gian nh của thuật toán
Best Case: 0 hoán ổi, n-1 so sánh (khi dãy ầu vào ã ược sắp)
Worst Case: n
2
/2 hoán ổi và so sánh (khi dãy ầu vào có thứ tự ngược lại với thứ tự cn sp xếp)
Average Case: n
2
/4 hoán ổi và so sánh
Là thuật toán sp xếp tốt ối với dãy ã gn ược sắp xếp
Nghĩa là mỗi phần tã ứng ở vị trí rất gần vị trí trong thứ tự cần sp xếp
# of Sorted elements Best case Worst case
0 0 0
1 1 1
2 1 2 … … … n-1 1 n-1
Số phép so sánh
22
Đánh giá ộ phức tạp nh toán của Inseron sort
lOMoARcPSD| 27879799
12
Vòng lặp for:
thực hiện n-1 lần
Gồm 5 câu lệnh (bao gồm cả câu lệnh gán và so sánh ở vòng lặp for)
Tổng chi phí cho vòng lặp for: 5(n-1)
Số lần vòng lặp while thực hiện phụ thuộc vào trạng thái sắp xếp các phần tử trong mảng:
Best case: mảng ầu vào ã ược sắp xếp do ó phép hoán ổi vị trí các phần tử trong mảng không ược
thực hiện lần nào.
Với mỗi giá trị k ở vòng lặp for, ta chỉ test iều kiện thực hiện vòng lặp while úng 1 lần (2 thao tác = 1
phép so sánh pos > 0 và 1 phép so sánh phần tử a[pos-1] > temp), các câu lệnh trong thân vòng lặp
while không bao giờ ược thực hiện
Do ó, tổng chi phí cho vòng lặp while trong toàn bộ chương trình là 2(n-1) thao tác.
Worst case: mảng ầu vào có thứ tự ngược với thứ tự cần sp xếp
Vòng lặp for thứ k: vòng lặp while thực hiện tổng cộng 4k+1 thao tác
Do ó, tổng chi phí cho vòng lặp while trong toàn bộ
chương trình là 2n(n-1)+n-1 Time cost:
Best case: 7(n-1)
Worst case: 5(n-1)+2n(n-1)+n-1
Các thuật toán sắp xếp
1. Sắp xếp chèn (Inseron sort)
2. Sắp xếp chọn (Selecon sort)
3. Sắp xếp nổi bọt (Bubble sort)
4. Sắp xếp trộn (Merge sort)
5. Sắp xếp nhanh (Quick sort)
6. Sắp xếp vun ống (Heap sort)
24
2. Sắp xếp chọn (Selecon sort)
lOMoARcPSD| 27879799
13
Mảng cần sp xếp ược chia làm 2 phần: sorted và unsorted
Những phần tử thuộc phần sorted: ã ược sắp xếp
Những phần tử thuộc phần unsorted: chưa ược sp xếp
Mỗi bước lặp: m phần tnhnhất thuộc phần unsorted, ri ổi vị trí phần tử nhnhất này với phần t
ầu ên của phần unsorted Sau mỗi bước lặp (sau mỗi thao tác chọn và hoán ổi): vách ngăn hai phần
sorted và unsorted dịch chuyển 1 vị trí sang phải, tức là số ợng phần tử thuộc phần sorted tăng lên 1,
và thuộc phần unsorted giảm i 1.
Mảng gồm n phần tsẽ cần n-1 bước lặp thực hiện xong sắp xếp.
Tại bước lặp i (i=0,1,..,n-2): m
phần tử nhnht của phần
unsorted (tức là các phần tử từ
a[i]…a[n-1]), rồi chuyển nó lên
vị trí thứ i của mng
25
2. Sắp xếp chọn (Selecon sort)
Thuật toán
Tìm phần tử nhnhất ưa vào vị trí 1 (a[0])
Tìm phần tử nhếp theo ưa vào vị trí
2 (a[1])
Tìm phần tử nhếp theo ưa vào vị trí
3
void seleconSort(int a[], int n){ int i, j, index_min;
for (i = 0; i < n-1; i++) {
//Tìm phần tử nhnhất từ a[i] ến phần tử cuối cùng trong mảng index_min = i;
for (j = i+1; j < n; j++) if (a[j] < a[index_min]) index_min = j; // ưa
phần tử a[index_min] vào v trí th i:
swap(&a[i], &a[index_min]);
}
}
void swap(int *a,int *b)
{ int temp = *a;
*a = *b;
*b = temp; }
NGUYỄN KHÁNH PHƯƠNG 26 KHMT
SOICT - ĐHBK HN
Đánh giá phức tạp nh toán của Selecon sort: O(n
2
)
lOMoARcPSD| 27879799
14
Thuật toán
Tìm phần tử nhnhất ưa vào vị trí 1 (a[0])
Tìm phần tử nhếp theo ưa vào vị trí 2
(a[1])
Tìm phần tử nhếp theo ưa vào vị trí 3
Đánh giá ộ phức tạp nh toán:
Best case: 0 phép ổi chỗ, n
2
/2 phép so sánh.
Worst case: n - 1 phép ổi chỗ, n
2
/2 phép so sánh.
Average case: O(n) phép ổi chỗ, n
2
/2 phép so sánh.
Ưu iểm nổi bật của sắp xếp chọn là số phép ổi chỗ là ít. Điều này là có ý nghĩa nếu
như việc ổi chỗ là tốn kém.
NGUYỄN KHÁNH PHƯƠNG 27 KHMT
SOICT - ĐHBK HN
Đánh giá phức tạp
void swap(int *a,int *b)
{ int temp = *a;
void seleconSort(int a[], int n){ int i, j, index_min;
for (i = 0; i < n-1; i++) { index_min = i;
//Tìm phần tử nhnht của phần unsorted: từ a[i+1] ến phần tử cuối cùng trong mng for (j = i+1; j < n; j++) if (a[j]
< a[index_min]) index_min = j; // ưa phần tử a[index_min] vào v trí th i: swap(&a[i],
&a[index_min]);
}
}
Hàm seleconSort: vòng lặp for ngoài thực hiện n-
1 Ta gọi hàm swap 1 lần tại mỗi bước lặp.
Tổng phép hoán đổi (swap): n-1
Tổng phép gán: 3*(n-1)
Vòng lặp for trong thực hiện số lần = kích thước phần unsorted - 1 (t
mỗi vòng lặp thực hiện phép so sánh 1 lần, do đó tng cng:
# phép so sánh = (n-1) + (n-2) + …. + 2 + 1 =
Vậy, đphức tạp của Selecon sort là O(
*a = *b;
*b = temp; }
lần.
vì mi phép swap có 3 phép đi
ch
n-1 tới 1),và
n*(n-1)/2
28
n
2
)
Kết luận: Đánh giá phức tp của Selecon sort: O(n
2
)
lOMoARcPSD| 27879799
15
Sắp xếp chọn là tại chỗ và n ịnh (In place and Stable)
Thời gian nh: O(n
2
) cho cả 3 trường hợp best/worse/average. Tc
là thuật toán không phụ thuộc vào ặc nh của dữ liệu ầu vào.
Mặc dù thuật toán sắp xếp chèn cần O(n
2
) phép so sánh, nhưng ch
thực hiện O(n) phép ổi chỗ.
– Nên chọn sắp xếp chọn nếu việc ổi chỗ là tốn kém, còn
phép so sánh ít tốn kém (trường hợp dữ liệu ầu vào:
short keys, long records).
NGUYỄN KHÁNH PHƯƠNG 29 KHMT –
SOICT - ĐHBK HN
Các thuật toán sắp xếp
1. Sắp xếp chèn (Inseron sort)
2. Sắp xếp chọn (Selecon sort)
3. Sắp xếp nổi bọt (Bubble sort)
4. Sắp xếp trộn (Merge sort)
5. Sắp xếp nhanh (Quick sort)
6. Sắp xếp vun ống (Heap sort)
30
"Bubbling Up" phần tử lớn nhất
lOMoARcPSD| 27879799
16
• Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
77
42
35
12
101
5
"Bubbling Up" phần tử lớn nhất
• Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
7742
Swap
4277 35 12 101 5
"Bubbling Up" phần tử lớn nhất
lOMoARcPSD| 27879799
17
Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
42 7735
Swap
3577 12 101 5
"Bubbling Up" phần tử lớn nhất
Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
42 35 7712
Swap
1277 101 5
"Bubbling Up" phần tử lớn nhất
lOMoARcPSD| 27879799
18
• Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
42
35
12
77
101
5
Không cần swap
"Bubbling Up" phần tử lớn nhất
Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
42 35 12 77 1015
Swap
1015
"Bubbling Up" the Largest Element
lOMoARcPSD| 27879799
19
Duyệt qua lần lượt các phần tử của mảng:
Từ trái sang phải (từ ầu dãy vcuối dãy)
“Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi)
a[0] a[1] a[2] a[3] a[4] a[5]
42
35
12
77
5
101
Phần tử có giá trị lớn nhất đã nằm đúng vị trí
Chú ý
Nhận thấy rằng mới chỉ có phần tử lớn nhất nằm úng vị trí của nó
trên mảng
Các phần tử khác vẫn chưa nằm úng vị trí
Vì vậy ta cn lặp lại ến trình vừa thực hiện
a[0] a[1] a[2] a[3] a[4] a[5]
42
35
12
77
5
101
Phần tử có giá trị lớn nhất đã nằm đúng vị
trí của nó trong mảng
Cần lặp lại ến trình “Bubble Up” bao nhiêu ln?
lOMoARcPSD| 27879799
20
Nếu mảng có n phần t
Mỗi ến trình “bubble up” ta chỉ di chuyển ược 1 phần tử về úng vị trí
của nó trong mảng…
Vậy ta cn lặp lại ến trình “bubble up” n – 1 lần ể ảm bảo tất cả n
phn tử của mảng ã cho ã về úng vị trí cần sp xếp.
NGUYỄN KHÁNH PHƯƠNG
KHMT – SOICT - ĐHBK HN
“Bubbling tất cả các phần tử
a[0] a[1] a[2] a[3] a[4] a[5]
Mảng ban đầu
1
st
iteraon
77
42
35
12
101
5
42
35
12
77
5
101
35
12
42
5
77
101
12
35
5
42
77
101
12
5
35
42
77
101
5
12
35
42
77
101
| 1/109

Preview text:

lOMoAR cPSD| 27879799
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
Cấu trúc dữ liệu và thuật toán Nguyễn Khánh Phương Computer Science department
School of Information and Communication technology
E-mail: phuongnk@soict.hust.edu.vn Nội dung khóa học
Chương 1. Các khái niệm cơ bản
Chương 2. Các sơ ồ thuật toán
Chương 3. Các cấu trúc dữ liệu cơ bản Chương 4. Cây Chương 5. Sắp xếp Chương 6. Tìm kiếm Chương 7. Đồ thị 2
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG 1 lOMoAR cPSD| 27879799 Chương 5. Sắp xếp Nguyễn Khánh Phương Computer Science department
School of Information and Communication technology
E-mail: phuongnk@soict.hust.edu.vn Bài toán sắp xếp
• Sắp xếp (Sorting) là quá trình tổ chức lại họ các dữ liệu theo thứ tự giảm dần hoặc tăng dần.
• Dữ liệu cần sắp xếp có thể là:
– Số nguyên/thực.. (integers/float)
– Xâu kí tự (character strings) – …
• Khóa sắp xếp (sort key)
– Là bộ phận của bản ghi xác ịnh thứ tự sắp xếp của bản ghi trong họ các bản ghi.
– Ta cần sắp xếp các bản ghi theo thứ tự của các khoá. – Ví dụ: khóa là tong = toan + ly + hoa
typedef struct{ char *ma; struct{ float toan, ly, hoa, tong; } DT; }thisinh;
typedef struct node{ thisinh data; struct node* next; 4 }node;
Các loại thuật toán sắp xếp 2 lOMoAR cPSD| 27879799
Sắp xếp trong (internal sort):
• Đòi hỏi họ dữ liệu ược ưa toàn bộ vào bộ nhớ trong của máy tính • Ví dụ: –
insertion sort (sắp xếp chèn), selection sort (sắp xếp lựa chọn), bubble sort (sắp xếp nổi bọt) –
quick sort (sắp xếp nhanh), merge sort (sắp xếp trộn), heap sort (sắp xếp vun ống), sample
sort (sắp xếp dựa mẫu), shell sort (vỏ sò) Sắp xếp ngoài (external sort):
• Họ dữ liệu không thể cùng lúc ưa toàn bộ vào bộ nhớ trong, nhưng có thể ọc vào từng bộ phận từ bộ nhớ ngoài
• Ví dụ:Poly-phase mergesort (trộn nhiều oạn), cascade-merge (thác nước), oscillating sort (dao ộng)
Sắp xếp song song (Parallel sort):
• Bitonic sort, Batcher even-odd sort.
• Smooth sort, cube sort, column sort. • GPU sort. 5
Các ặc trưng của một thuật toán sắp xếp
• Tại chỗ (in place): nếu không gian nhớ phụ mà thuật toán òi hỏi là O(1), nghĩa là bị
chặn bởi hằng số không phụ thuộc vào ộ dài của dãy cần sắp xếp.
• Ổn ịnh (stable): Nếu các phần tử có cùng giá trị vẫn giữ nguyên thứ tự tương ối của
chúng như trước khi sắp xếp. Bài toán sắp xếp 3 lOMoAR cPSD| 27879799 •
Có hai phép toán cơ bản mà thuật toán sắp xếp thường phải sử dụng:
– Đổi chỗ (Swap): Thời gian thực hiện là O(1) void swap( datatype *a, datatype
*b){ datatype *temp = *a; //datatype-kiểu dữ liệu của phần tử *a = *b; *b = *temp; }
– So sánh: Compare(a, b) trả lại true nếu a i trước b trong thứ tự cần sắp xếp và false nếu trái lại. •
Phân tích thuật toán sắp xếp: thông thường, các thuật toán sẽ sử dụng phép toán so sánh ể xác
ịnh thứ tự giữa hai phần tử rồi thực hiện ổi chỗ nếu
cần. Khi phân tích thuật toán sắp xếp, ta sẽ chỉ cần ếm số phép toán so sánh và số
lần dịch chuyển các phần tử (bỏ qua các phép toán khác không ảnh hưởng ến kết quả). 7 Bài toán sắp xếp
• Các thuật toán chỉ sử dụng phép toán so sánh ể xác ịnh thứ tự giữa hai
phần tử ược gọi là thuật toán sử dụng phép so sánh (Comparison-based sorting algorithm).
• Nếu có những thông tin bổ sung về dữ liệu ầu vào, ví dụ như:
– Các số nguyên nằm trong khoảng [0..k] trong ó k = O(n)
– Các số thực phân bố
ều trong khoảng [0, 1) ta sẽ có thuật toán
tốt hơn thuật toán sắp xếp chỉ dựa vào phép so sánh.
(Thuật toán thời gian tuyến tính: sắp xếp
ếm (couting-sort), sắp xếp theo cơ số (radixsort), sắp xếp óng gói (bucket-sort)) 8
Các thuật toán sắp xếp 4 lOMoAR cPSD| 27879799
Khi so sánh các thuật toán, thông thường quan tâm ến:
• Thời gian chạy. Đối với các dữ liệu rất lớn, các thuật toán không hiệu quả
sẽ chạy rất chậm và không thể ứng dụng trong thực tế.
• Bộ nhớ. Các thuật toán nhanh òi hỏi ệ quy sẽ có thể phải tạo ra các bản
copy của dữ liệu ang xử lí. Với những hệ thống mà bộ nhớ có giới hạn (ví
dụ embedded system), một vài thuật toán sẽ không thể chạy ược.
• Độ ổn ịnh (stability). Độ ổn ịnh ược ịnh nghĩa dựa trên iều gì sẽ xảy ra với
các phần tử có giá trị giống nhau.
– Đối với thuật toán sắp xếp ổn ịnh, các phần tử với giá trị bằng nhau sẽ
giữ nguyên thứ tự trong mảng trước và sau khi sắp xếp.
– Đối với thuật toán sắp xếp không ổn ịnh, các phần tử có giá trị bằng
nhau sẽ có thể có thứ tự bất kỳ. 9
Tiêu chí lựa chọn giải thuật
Nhiều yếu tố ảnh hưởng: • Ổn ịnh •
Danh sách liên kết hay mảng •
Đặc trưng của dữ liệu cần sắp xếp: – Nhiều khóa ?
– Các khóa là phân biệt ? – Nhiều dạng khóa ?
– Kích thước bản ghi lớn hay nhỏ ? – Dữ liệu
ược sắp xếp ngẫu nhiên?
Không thể bao phủ tất cả các yếu tố Nội dung 5 lOMoAR cPSD| 27879799
1. Sắp xếp chèn (Insertion sort)
2. Sắp xếp chọn (Selection sort)
3. Sắp xếp nổi bọt (Bubble sort)
4. Sắp xếp trộn (Merge sort)
5. Sắp xếp nhanh (Quick sort)
6. Sắp xếp vun ống (Heap sort)
1. Sắp xếp chèn (Insertion sort)
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một con bài vào
bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó bởi việc
dịch chuyển đầu tiên là 36 và sau đó là 24. 12
1. Sắp xếp chèn (Insertion sort) 6 lOMoAR cPSD| 27879799
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một
con bài vào bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó
bởi việc dịch chuyển đầu tiên là 36 và sau đó là 24. 13
1. Sắp xếp chèn (Insertion sort)
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một
con bài vào bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó
bởi việc dịch chuyển đầu tiên là 36 và sau đó là 24. 14
1. Sắp xếp chèn (Insertion sort) 7 lOMoAR cPSD| 27879799
Phỏng theo cách làm của người chơi bài khi cần "chèn" thêm một con
bài vào bộ bài đã được sắp xếp trên tay.
Để chèn 12, ta cần tạo chỗ cho nó bởi
việc dịch chuyển đầu tiên là 36 và sau đó là 24. 15
1. Sắp xếp chèn (Insertion sort) Thuật toán:
• Mảng cần sắp xếp ược chia làm 2 phần, sorted và unsorted: – Những phần
tử nằm trong phần sorted: ã ược sắp xếp
– Những phần tử nằm trong phần unsorted: chưa ược sắp xếp
• Mỗi bước lặp: phần tử ầu tiên thuộc phần unsorted sẽ ược chuyển sang phần sorted.
Mảng có n phần tử sẽ cần n-1 bước lặp ể sắp xếp xong 16 8 lOMoAR cPSD| 27879799 n- k
úng vị trí trong dãy gồm k
Dịch tất cả các phần tử a[pos]… a[k-1] sang phải 1 vị trí n- k
úng vị trí trong dãy gồm
Tại mỗi bước lặp , có thể cần nhiều hơn một lần hoán đổi vị trí các phần tử để có thể đưa phần tử thứ
về đúng vị trí của nó trong dãy cần sắp xếp k 9 lOMoAR cPSD| 27879799 10 lOMoAR cPSD| 27879799 Cài
ặt: Insertion Sort Algorithm NGUYỄN KHÁNH PHƯƠNG 21 KHMT – SOICT - ĐHBK HN Đánh giá
ộ phức tạp tính toán của Insertion sort: O(n2)
• Sắp xếp chèn là tại chỗ và ổn ịnh (In place and Stable)
• Phân tích thời gian tính của thuật toán –
Best Case: 0 hoán ổi, n-1 so sánh (khi dãy ầu vào là ã ược sắp) –
Worst Case: n2/2 hoán ổi và so sánh (khi dãy ầu vào có thứ tự ngược lại với thứ tự cần sắp xếp) –
Average Case: n2/4 hoán ổi và so sánh
• Là thuật toán sắp xếp tốt
ối với dãy ã gần ược sắp xếp –
Nghĩa là mỗi phần tử ã ứng ở vị trí rất gần vị trí trong thứ tự cần sắp xếp # of Sorted elements Best case Worst case 0 0 0 1 1 1 2 1 2 … … … n-1 1 n-1 Số phép so sánh 22
Đánh giá ộ phức tạp tính toán của Insertion sort 11 lOMoAR cPSD| 27879799 Vòng lặp for: • thực hiện n-1 lần
• Gồm 5 câu lệnh (bao gồm cả câu lệnh gán và so sánh ở vòng lặp for)
Tổng chi phí cho vòng lặp for: 5(n-1)
Số lần vòng lặp while thực hiện phụ thuộc vào trạng thái sắp xếp các phần tử trong mảng:
• Best case: mảng ầu vào ã
ược sắp xếp do ó phép hoán ổi vị trí các phần tử trong mảng không ược thực hiện lần nào.
– Với mỗi giá trị k ở vòng lặp for, ta chỉ test iều kiện thực hiện vòng lặp while úng 1 lần (2 thao tác = 1
phép so sánh pos > 0 và 1 phép so sánh phần tử a[pos-1] > temp), các câu lệnh trong thân vòng lặp while không bao giờ ược thực hiện
– Do ó, tổng chi phí cho vòng lặp while trong toàn bộ chương trình là 2(n-1) thao tác.
• Worst case: mảng ầu vào có thứ tự ngược với thứ tự cần sắp xếp
– Vòng lặp for thứ k: vòng lặp while thực hiện tổng cộng 4k+1 thao tác
– Do ó, tổng chi phí cho vòng lặp while trong toàn bộ
chương trình là 2n(n-1)+n-1 Time cost: – Best case: 7(n-1)
– Worst case: 5(n-1)+2n(n-1)+n-1
Các thuật toán sắp xếp
1. Sắp xếp chèn (Insertion sort)
2. Sắp xếp chọn (Selection sort)
3. Sắp xếp nổi bọt (Bubble sort)
4. Sắp xếp trộn (Merge sort)
5. Sắp xếp nhanh (Quick sort)
6. Sắp xếp vun ống (Heap sort) 24
2. Sắp xếp chọn (Selection sort) 12 lOMoAR cPSD| 27879799
• Mảng cần sắp xếp ược chia làm 2 phần: sorted và unsorted
– Những phần tử thuộc phần sorted: ã ược sắp xếp
– Những phần tử thuộc phần unsorted: chưa ược sắp xếp
• Mỗi bước lặp: tìm phần tử nhỏ nhất thuộc phần unsorted, rồi ổi vị trí phần tử nhỏ nhất này với phần tử
ầu tiên của phần unsorted Sau mỗi bước lặp (sau mỗi thao tác chọn và hoán ổi): vách ngăn hai phần
sorted và unsorted dịch chuyển 1 vị trí sang phải, tức là số lượng phần tử thuộc phần sorted tăng lên 1,
và thuộc phần unsorted giảm i 1.
• Mảng gồm n phần tử sẽ cần n-1 bước lặp
ể thực hiện xong sắp xếp.
Tại bước lặp i (i=0,1,..,n-2): tìm
phần tử nhỏ nhất của phần
unsorted (tức là các phần tử từ
a[i]…a[n-1]), rồi chuyển nó lên
vị trí thứ i của mảng 25
2. Sắp xếp chọn (Selection sort) Thuật toán
• Tìm phần tử nhỏ nhất ưa vào vị trí 1 (a[0])
• Tìm phần tử nhỏ tiếp theo ưa vào vị trí 2 (a[1])
• Tìm phần tử nhỏ tiếp theo ưa vào vị trí 3 • … void swap(int *a,int *b) { int temp = *a; *a = *b; *b = temp; }
void selectionSort(int a[], int n){ int i, j, index_min;
for (i = 0; i < n-1; i++) {
//Tìm phần tử nhỏ nhất từ a[i] ến phần tử cuối cùng trong mảng index_min = i;
for (j = i+1; j < n; j++) if (a[j] < a[index_min]) index_min = j; // ưa
phần tử a[index_min] vào vị trí thứ i:
swap(&a[i], &a[index_min]); }
NGUYỄN KHÁNH PHƯƠNG 26 KHMT – } SOICT - ĐHBK HN Đánh giá
ộ phức tạp tính toán của Selection sort: O(n2) 13 lOMoAR cPSD| 27879799 Thuật toán
• Tìm phần tử nhỏ nhất ưa vào vị trí 1 (a[0])
• Tìm phần tử nhỏ tiếp theo ưa vào vị trí 2 (a[1])
• Tìm phần tử nhỏ tiếp theo ưa vào vị trí 3 • …
Đánh giá ộ phức tạp tính toán:
• Best case: 0 phép ổi chỗ, n2/2 phép so sánh.
• Worst case: n - 1 phép ổi chỗ, n2/2 phép so sánh.
• Average case: O(n) phép ổi chỗ, n2/2 phép so sánh.
• Ưu iểm nổi bật của sắp xếp chọn là số phép
ổi chỗ là ít. Điều này là có ý nghĩa nếu như việc ổi chỗ là tốn kém.
NGUYỄN KHÁNH PHƯƠNG 27 KHMT – SOICT - ĐHBK HN void swap(int *a,int *b) Đánh giá ộ phức tạp { int temp = *a;
void selectionSort(int a[], int n){ int i, j, index_min; *a = *b;
for (i = 0; i < n-1; i++) { index_min = i; *b = temp; }
//Tìm phần tử nhỏ nhất của phần unsorted: từ a[i+1] ến phần tử cuối cùng trong mảng for (j = i+1; j < n; j++) if (a[j]
< a[index_min]) index_min = j; // ưa phần tử a[index_min] vào vị trí thứ i: swap(&a[i], &a[index_min]); } }
Hàm selectionSort: vòng lặp for ngoài thực hiện n-
1 Ta gọi hàm swap 1 lần tại mỗi bước lặp.
Tổng phép hoán đổi (swap): n-1 Tổng phép gán: 3*(n-1) lần.
Vòng lặp for trong thực hiện số lần = kích thước phần unsorted - 1 (từ
mỗi vòng lặp thực hiện phép so sánh 1 lần, do đó tổng cộng:
# phép so sánh = (n-1) + (n-2) + v …. ì mỗ + i p 2 hé + p 1 = sw ap có 3 phép đổi
Vậy, độ phức tạp của Selection sort là O( chỗ n-1 tới 1),và n*(n-1)/2 28 n2) Kết luận: Đánh giá
ộ phức tạp của Selection sort: O(n2) 14 lOMoAR cPSD| 27879799
• Sắp xếp chọn là tại chỗ và ổn ịnh (In place and Stable)
• Thời gian tính: O(n2) cho cả 3 trường hợp best/worse/average. Tức
là thuật toán không phụ thuộc vào ặc tính của dữ liệu ầu vào.
• Mặc dù thuật toán sắp xếp chèn cần O(n2) phép so sánh, nhưng chỉ
thực hiện O(n) phép ổi chỗ.
– Nên chọn sắp xếp chọn nếu việc
ổi chỗ là tốn kém, còn
phép so sánh ít tốn kém (trường hợp dữ liệu ầu vào: short keys, long records).
NGUYỄN KHÁNH PHƯƠNG 29 KHMT – SOICT - ĐHBK HN
Các thuật toán sắp xếp
1. Sắp xếp chèn (Insertion sort)
2. Sắp xếp chọn (Selection sort)
3. Sắp xếp nổi bọt (Bubble sort)
4. Sắp xếp trộn (Merge sort)
5. Sắp xếp nhanh (Quick sort)
6. Sắp xếp vun ống (Heap sort) 30
"Bubbling Up" phần tử lớn nhất 15 lOMoAR cPSD| 27879799
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] 77 42 35 12 101 5
"Bubbling Up" phần tử lớn nhất
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] Swap 7742 4277 35 12 101 5
"Bubbling Up" phần tử lớn nhất 16 lOMoAR cPSD| 27879799
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] Swap 42 7735 3577 12 101 5
"Bubbling Up" phần tử lớn nhất
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] Swap 42 35 7712 1277 101 5
"Bubbling Up" phần tử lớn nhất 17 lOMoAR cPSD| 27879799
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] 42 35 12 77 101 5 Không cần swap
"Bubbling Up" phần tử lớn nhất
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] Swap 42 35 12 77 1015 1015
"Bubbling Up" the Largest Element 18 lOMoAR cPSD| 27879799
• Duyệt qua lần lượt các phần tử của mảng:
– Từ trái sang phải (từ ầu dãy về cuối dãy)
– “Bubble” phần tử có giá trị lớn nhất về cuối mảng bằng cách thực
hiện các cặp lệnh (so sánh, hoán ổi) a[0] a[1] a[2] a[3] a[4] a[5] 42 35 12 77 5 101
Phần tử có giá trị lớn nhất đã nằm đúng vị trí Chú ý
• Nhận thấy rằng mới chỉ có phần tử lớn nhất nằm úng vị trí của nó trên mảng
• Các phần tử khác vẫn chưa nằm úng vị trí
• Vì vậy ta cần lặp lại tiến trình vừa thực hiện a[0] a[1] a[2] a[3] a[4] a[5] 42 35 12 77 5 101
Phần tử có giá trị lớn nhất đã nằm đúng vị trí của nó trong mảng
Cần lặp lại tiến trình “Bubble Up” bao nhiêu lần? 19 lOMoAR cPSD| 27879799
• Nếu mảng có n phần tử…
• Mỗi tiến trình “bubble up” ta chỉ di chuyển ược 1 phần tử về úng vị trí của nó trong mảng…
• Vậy ta cần lặp lại tiến trình “bubble up” n – 1 lần ể ảm bảo tất cả n phần tử của mảng
ã cho ã về úng vị trí cần sắp xếp. NGUYỄN KHÁNH PHƯƠNG KHMT – SOICT - ĐHBK HN
“Bubbling” tất cả các phần tử 77 42 35 12 101 5 42 35 12 77 5 101 35 12 42 5 77 101 12 35 5 42 77 101 12 5 35 42 77 101 5 12 35 42 77 101 a[0] a[1] a[2] a[3] a[4] a[5] Mảng ban đầu 1st iteration 20