Chương 2.2. Giải thuật sắp xếp
ầ
Tr n Minh Thái Email: minhthai@huflit.edu.vn Website: www.minhthai.edu.vn
1
Mục tiêu
Nắm vững, minh họa và tính toán được
các phép so sánh, phép gán/ hoán vị của
các giải thuật sắp xếp cơ bản trên mảng
một chiều
Cài đặt được các giải thuật bằng ngôn
ngữ C#
2
Các khái niệm
Để truy xuất thông tin nhanh chóng và chính xác thông tin phải được sắp xếp theo một trật tự hợp lý nào đó
Một số CTDL đã định nghĩa trước trật tự của các phần tử, khi đó mỗi phần tử khi thêm vào phải đảm bảo trật tự này
Sắp xếp là quá trình xử lý một danh sách các phần tử (hoặc các mẫu tin) để đặt chúng theo một thứ tự thỏa mãn một tiêu chuẩn nào đó dựa trên nội dung thông tin lưu giữ tại mỗi phần tử
3
Các khái niệm
Khái niệm nghịch thế
a1 a2 a3
a4 … … aN-
aN
aN- 1
2
Giả sử xét mảng có thứ tự tăng dần, nếu có
i
Mục tiêu của sắp xếp là khử các nghịch thế
4
(bằng cách hoán vị)
Các khái niệm
Tương tự như các giải thuật tìm kiếm, khối lượng công việc phải thực hiện có liên quan chặt chẽ với số lần so sánh các khóa
Ngoài ra, các giải thuật sắp xếp còn phải di
chuyển các phần tử
5
Chiếm nhiều thời gian khi các phần tử có kích thước lớn
Các giải thuật sắp xếp cơ bản
Đổi chổ trực tiếp – Interchange Sort
Chọn trực tiếp – Selection Sort
Chèn trực tiếp – Insertion Sort
Nổi bọt – Bubble Sort
Quick Sort
Một số giải thuật khác đọc thêm trong tài
liệu
6
Đổi chổ trực tiếp – interchange sort
Ý tưởng
Ý tưởng chính của giải thuật là xuất phát từ đầu
dãy, tìm tất cả nghịch thế chứa phần tử này, triệt
tiêu chúng bằng cách đổi chỗ phần tử này với
phần tử tương ứng trong cặp nghịch thế. Lặp lại
7
xử lý trên với các phần tử tiếp theo trong dãy.
Đổi chổ trực tiếp – interchange sort Giả sử cần sắp xếp dãy số sau tăng dần
15
10
9
7
5
1 2 3
3 4
5
2 6
7
1 8
8
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
3
3 4
5
2 6
7
1 8
9
1 2
i j
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
3
3 4
5
2 6
7
1 8
10
2 1
j i
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
2 3 1 5
3 4
2 6
7
1 8
11
j i
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
2 3
3 1
4 5
2 6
7
1 8
12
i j
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
2 3 4
3 1
7
2 6
1 8
13
5
i j
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
2 3 4 5
2 1
7
3 6
1 8
14
i j
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
15
10
9
7
5
2 3 4 5
3 6
2 1
7
1 8
15
i j
Đổi chổ trực tiếp – interchange sort Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
Kết thúc bước 1 15
10
9
7
5
2 3 4 5
3 6
7
1 1 1
2 8
16
i j
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
15
10
9
7
5
2 3
1 1 1
5 4
3 6
7
2 8
17
j i
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
15
10
9
7
5
1 1 1
3 2 5 4
3 6
7
2 8
18
j i
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
15
10
9
7
5
1 1 1
2 3 4 5
3 6
7
2 8
19
i j
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
15
10
9
7
5
3 4
1 1 1
2 7
3 6
2 8
20
5
i j
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
15
10
9
7
5
3 4 5
1 1 1
3 2
7
2 8
21
6
i j
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
15
10
9
7
5
3 4 5 6
1 1 1
3 2
7
2 8
22
i j
Đổi chổ trực tiếp – interchange sort Bước 2: Xét phần tử thứ hai (tại vị trí 2)
Kết thúc bước 2 15
10
9
7
5
3 4 5 6 7
1 1 1
2 2 2
3 8
23
i j
Đổi chổ trực tiếp – interchange sort Bước 3: Xét phần tử thứ ba (tại vị trí 3)
15
10
9
7
5
3 4
1 1 1
2 2 2
5 6 7
3 8
24
j i
Đổi chổ trực tiếp – interchange sort Bước 3: Xét phần tử thứ ba (tại vị trí 3)
15
10
9
7
5
1 1 1
2 2 2
4 3 5 6 7
3 8
25
j i
Đổi chổ trực tiếp – interchange sort Bước 3: Xét phần tử thứ ba (tại vị trí 3)
15
10
9
7
5
1 1 1
2 2 2
4 5 3 7 6
3 8
26
j i
Đổi chổ trực tiếp – interchange sort Bước 3: Xét phần tử thứ ba (tại vị trí 3)
15
10
9
7
5
1 1 1
2 2 2
4 5 3 7
3 8
27
6
i j
Đổi chổ trực tiếp – interchange sort Bước 3: Xét phần tử thứ ba (tại vị trí 3)
15
10
9
7
5
1 1 1
2 2 2
4 5 6 3 7
3 8
28
i j
Đổi chổ trực tiếp – interchange sort Bước 3: Xét phần tử thứ ba (tại vị trí 3)
Kết thúc bước 3 15
10
9
7
5
4 5 6 7 8
1 1 1
2 2 2
3 3 3
29
j i
Đổi chổ trực tiếp – interchange sort Bước 4: Xét phần tử thứ tư (tại vị trí 4)
15
10
9
7
5
1 1 1
2 2 2
4 5
3 3 3
30
7 6 8
j i
Đổi chổ trực tiếp – interchange sort Bước 4: Xét phần tử thứ tư (tại vị trí 4)
15
10
9
7
5
1 1 1
2 2 2
3 3 3
31
7 6 8 4 5
i j
Đổi chổ trực tiếp – interchange sort Bước 4: Xét phần tử thứ tư (tại vị trí 4)
15
10
9
7
5
1 1 1
2 2 2
3 3 3
32
5 6 4 7 8
j i
Đổi chổ trực tiếp – interchange sort Bước 4: Xét phần tử thứ tư (tại vị trí 4)
15
10
9
7
5
1 1 1
2 2 2
3 3 3
33
5 6 4 7 8
i j
Đổi chổ trực tiếp – interchange sort Bước 4: Xét phần tử thứ tư (tại vị trí 4)
Kết thúc bước 4 15
10
9
7
5 5
1 1 1
2 2 2
3 3 3
34
5 6 7 4 8
i j
Đổi chổ trực tiếp – interchange sort Bước 5: Xét phần tử thứ năm (tại vị trí 5)
15
10
9
7
5 5
1 1 1
2 2 2
3 3 3
35
5 6 4 7 8
j i
Đổi chổ trực tiếp – interchange sort Bước 5: Xét phần tử thứ năm (tại vị trí 5)
15
10
9
7
5 5
1 1 1
2 2 2
3 3 3
36
4 8 7 5 6
i j
Đổi chổ trực tiếp – interchange sort Bước 5: Xét phần tử thứ năm (tại vị trí 5)
15
10
9
7
5 5
1 1 1
2 2 2
3 3 3
37
4 6 7 5 8
j i
Đổi chổ trực tiếp – interchange sort Bước 5: Xét phần tử thứ năm (tại vị trí 5)
Kết thúc bước 5 15
10
9
7 7
5 5
1 1 1
2 2 2
3 3 3
38
4 6 7 8 5
j i
Đổi chổ trực tiếp – interchange sort Bước 6: Xét phần tử thứ sáu (tại vị trí 6)
15
10
9
7 7
5 5
1 1 1
2 2 2
3 3 3
39
4 6 7 5 8
j i
Đổi chổ trực tiếp – interchange sort Bước 6: Xét phần tử thứ sáu (tại vị trí 6)
15
10
9
7 7
5 5
1 1 1
2 2 2
3 3 3
40
4 5 6 7 8
i j
Đổi chổ trực tiếp – interchange sort Bước 6: Xét phần tử thứ sáu (tại vị trí 6)
Kết thúc bước 6 15
10
9 9
7 7
5 5
1 1 1
2 2 2
3 3 3
41
4 5 7 8 6
j i
Đổi chổ trực tiếp – interchange sort Bước 7: Xét phần tử thứ bảy (tại vị trí 7)
15
10
9 9
7 7
5 5
1 1 1
2 2 2
3 3 3
42
4 5 7 8 6
j i
Đổi chổ trực tiếp – interchange sort Bước 7: Xét phần tử thứ bảy (tại vị trí 7)
Kết thúc bước 7
15
10 10
9 9
7 7
5 5
1 1 1
2 2 2
3 3 3
43
4 5 6 7 8
i j
Đổi chổ trực tiếp – interchange sort Hoàn tất sắp xếp
15
10 10
9 9
7 7
5 5
11 1
2 2 2
3 3 3
44
4 5 6 7 8
Giải thuật
Bước 1 : i = 1;// bắt đầu từ đầu dãy
Bước 2 : j = i+1;//tìm các phần tử a[j] < a[i], j>i
Bước 3 :
Trong khi j <= N thực hiện
Nếu a[j]
Bước 4 : i = i+1; j = j+1; Nếu i < N: Lặp lại Bước 2. 45 Ngược lại: Dừng. Cài đặt void InterchangeSort(int []a, int N ) { int i, j; for (i = 0 ; i for (j =i+1; j < N ; j++)
if(a[j ]< a[i]) HoanVi(ref a[i], ref a[j]); } } void HoanVi(ref int a, ref int b)
{ 46 int tam=a;
a=b;
b=tam; } § Minh họa từng bước thực hiện của giải thuật
Interchange Sort khi sắp dãy số sau tăng dần: § Cho biết tổng số phép hoán vị 47 1 2 3 4 5 6 Ðánh giá giải thuật 48 Số lượng các phép so sánh xảy ra không phụ
thuộc vào tình trạng của dãy số ban đầu, nhưng
số lượng phép hoán vị thực hiện tùy thuộc vào kết
quả so sánh, có thể ước lượng: Đổi chổ trực tiếp – Interchange Sort Chọn trực tiếp – Selection Sort Nổi bọt – Bubble Sort Chèn trực tiếp – Insertion Sort Quick Sort 49 Ý tưởng: Chọn phần tử nhỏ nhất trong N phần tử ban đầu, đưa phần tử này về vị trí đúng là đầu dãy hiện hành (vị trí 1); Dãy hiện hành còn lại N-1 phần tử cần sắp xếp (từ vị trí 2 đến N), lặp lại quá trình trên cho dãy hiện hành... Thực hiện cho đến khi dãy hiện hành chỉ còn 1 phần 50 tử Làm sao để xác định được vị trí phần tử có giá trị nhỏ nhất trong một dãy
gồm N phần tử? 51 1 2 3 5 7 52 1 2 3 5 7 53 54 1 2 3 5 7 7 lớn hơn 5
nên không
cập nhật vị
trí min 55 1 2 3 5 7 3 nhỏ hơn 5
nên cập
nhật vị trí
min 56 1 2 3 5 7 9 lớn hơn 3
nên không
cập nhật vị
trí min 57 1 2 3 5 7 1 nhỏ hơn 3
nên cập
nhật vị trí
min 58 1 2 3 5 7 15 lớn hơn 1
nên không
cập nhật vị
trí min 59 1 2 3 5 7 2 lớn hơn 1
nên không
cập nhật vị
trí min 60 1 2 3 5 7 Bước 1: i=2, vt=1; Bước 2: Nếu i>N thì trả về giá trị vt, kết thúc; Bước 3: Nếu a[i]
i=i+1; 61 Quay lại Bước 2; int TimVTMin(int []a, int n) { int vtmin=0; int i=1; while(i { if(a[i]
vtmin=i; i++; } 62 return vtmin; } Hãy cài đặt hàm tìm và trả về vị trí
của phần tử nhỏ nhất bằng ngôn ngữ C#,
đầu vào là mảng số nguyên a, kích thước
N? 63 64 1 3 5 7 8 Giả sử cần sắp xếp dãy số sau tăng
dần 1 2 3 5 7 65 Bước 1: Xét phần tử thứ nhất (vị trí
• Tìm phần tử nhỏ nhất từ vị trí 1 đến 8
1)
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 1 2 3 5 66 7 i Bước 2: Xét phần tử thứ hai (vị trí 2)
• Tìm phần tử nhỏ nhất từ vị trí 2 đến 8
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 2 3 5 67 7 8 i Bước 3: Xét phần tử thứ ba (vị trí 3)
• Tìm phần tử nhỏ nhất từ vị trí 3 đến 8
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 3 68 5 6 7 8 i Bước 4: Xét phần tử thứ tư (vị trí 4)
• Tìm phần tử nhỏ nhất từ vị trí 4 đến 8
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 4 5 6 7 8 69 i Bước 5: Xét phần tử thứ năm (vị trí
• Tìm phần tử nhỏ nhất từ vị trí 5 đến 8
5)
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 70 5 6 7 8 4 i Bước 6: Xét phần tử thứ sáu (vị trí
6)• Tìm phần tử nhỏ nhất từ vị trí 6 đến 8
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 71 4 6 5 7 8 i Bước 7: Xét phần tử thứ bảy (vị trí
7)• Tìm phần tử nhỏ nhất từ vị trí 7 đến 8
• Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min min 72 4 5 7 8 6 i Kết thúc giải thuật - hoàn tất sắp
xếp 73 4 5 6 7 8 Giải thuật
Bước 1: i = 1; Bước 2: Tìm phần tử a[vtmin] nhỏ nhất trong
dãy hiện hành từ a[i] đến a[N] Bước 3: Hoán vị a[vtmin] và a[i] Bước 4: i = i+1 Nếu i < N thì lặp lại Bước 2 Ngược lại: Dừng. 74 { int vtmin; Tìm vị trí min
tính từ i đến N-
1 for (int i=0; i {
vtmin = i; for(int j = i+1; j { if (a[j ] < a[vtmin]) 75 vtmin=j; } HoanVi(ref a[vtmin], ref a[i]); } } int TimVTMin(int []a, int N, int k) { int vtmin=k;Bài tập
15
7
9
10
6
20
§ Cài đặt phương thức sắp xếp theo phương
pháp trên vào lớp CMyIntArray (có tính số
phép so sánh và gán)
Các giải thuật sắp xếp cơ bản
Chọn trực tiếp – selection sort
Chọn trực tiếp – selection sort
?
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Giả sử cần tìm vị trí phần tử nhỏ nhất trong
dãy số sau ?
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 1: Giả sử vị trí phần tử nhỏ nhất là 1
(vtmin), phần tử này có giá trị 10
vtmi
n
15
10
9
7
5
3
4
1
6
2
8
vtmi
n
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
5 nhỏ hơn
phần tử nào nhỏ hơn phần tử tại vtmin thì
10 nên cập
cập nhật lại vtmin
nhật vị trí
min
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
phần tử nào nhỏ hơn phần tử tại vtmin thì
cập nhật lại vtmin
vtmi
n
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
phần tử nào nhỏ hơn phần tử tại vtmin thì
cập nhật lại vtmin
vtmi
n
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
phần tử nào nhỏ hơn phần tử tại vtmin thì
cập nhật lại vtmin vtmi
n
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
phần tử nào nhỏ hơn phần tử tại vtmin thì
cập nhật lại vtmin vtmi
n
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
phần tử nào nhỏ hơn phần tử tại vtmin thì
cập nhật lại vtmin
vtmi
n
15
10
9
7
5
3
4
1
6
2
8
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Bước 2: So sánh giá trị tại vtmin với tất cả
giá trị tại vị trí còn lại (từ 2 đến 8), nếu có
phần tử nào nhỏ hơn phần tử tại vtmin thì
cập nhật lại vtmin
vtmi
n
15
10
9
7
5
3
4
1
6
2
8
Giải thuật tìm vị trí phần tử
nhỏ nhất
Vấn đề tìm vị trí phần tử nhỏ
nhất?
?
Vấn đề tìm vị trí phần tử nhỏ
nhất?
Giả sử cần tìm vị trí phần tử nhỏ nhất
bắt đầu từ vị trí k cho trước (ví dụ
?
đoạn
từ 3 đến 8) thì giải quyết như thế
nào? Hãy viết hàm cài đặt bằng ngôn ngữ
C#?
15
10
9
8
7
3
4
1
2
2
6
Chọn trực tiếp – selection sort
15
10
9
7
5
3
4
2
6
1
8
Chọn trực tiếp – selection sort
15
10
9
7
5
3
4
2
6
1
8
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
3
4
2
6
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
2
2
3
4
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
2
2
3
3
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
2
2
3
3
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
2
2
3
3
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
2
2
3
3
Chọn trực tiếp – selection sort
15
10
9
7
5
1
1
2
2
3
3
Cài đặt 1
void SelectionSort(int []a, int N )

