You are on page 1of 31

Các khái niệm

 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
CHƯƠNG 2. SẮP XẾP 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ử.

Biên soạn: ThS.Phạm Văn Đăng


Email: pvdang@ntt.edu.vn

Mục tiêu Các khái niệm

 Nắm vững, minh họa và tính toán được các  Khái niệm nghịch thế
a1 a2 a3 a4 … … aN-2 aN-1 aN
phép gán (hoán vị) các giải thuật sắp xếp cơ
Giả sử xét mảng có thứ tự tăng dần, nếu có i<j và ai>aj
bản trên mảng một chiều
thì ta gọi đó là nghịch thế.
 Cài đặt được các giải thuật bằng ngôn ngữ Java Giả sử xét mảng có thứ tự giảm dần, nếu có i<j và ai<aj
thì ta gọi đó là nghịch thế.
Mục tiêu của sắp xếp là khử các nghịch thế (bằng cách
hoán vị)
2 4
Đổi chổ trực tiếp – interchange sort
Các giải thuật sắp xếp cơ bản
Giả sử cần sắp xếp dãy số sau tăng dần

 Đổi chổ trực tiếp – Interchange Sort


 Chọn trực tiếp – Selection Sort
 Nổi bọt – Bubble Sort 15
 Chèn trực tiếp – Insertion Sort 10 9
5 7
 Quick Sort
3 2 1
 Một số giải thuật khác đọc thêm trong tài liệu 1 2 3 4 5 6 7 8

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 1: Xét phần tử đầu tiên (tại vị trí 1)
 Ý 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 15
10 9
5 7
tiêu chúng bằng cách đổi chỗ phần tử này với 3 2 1
phần tử tương ứng trong cặp nghịch thế. Lặp lại 1 2 3 4 5 6 7 8

xử lý trên với các phần tử tiếp theo trong dãy. 8

i j
6
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 1: Xét phần tử đầu tiên (tại vị trí 1) Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

15 15
10 9 10 9
5 7 7 5
3 2 1 3 2 1
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

9 11

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 1: Xét phần tử đầu tiên (tại vị trí 1) Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

15 15
10 9 10 9
5 7 7 5
3 2 1 3 2 1
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

10 12

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 1: Xét phần tử đầu tiên (tại vị trí 1) Bước 1: Xét phần tử đầu tiên (tại vị trí 1)

Kết thúc
bước 1
15 15
10 9 10 9
7 5 7 5
2 3 1 1 3 2
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

13 15

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 1: Xét phần tử đầu tiên (tại vị trí 1) Bước 2: Xét phần tử thứ hai (tại vị trí 2)

15 15
10 9 10 9
7 5 7 5
2 3 1 1 3 2
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

14 16

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 2: Xét phần tử thứ hai (tại vị trí 2) Bước 2: Xét phần tử thứ hai (tại vị trí 2)

15 15
10 9 10 9
7 5 5 7
1 3 2 1 3 2
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

17 19

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 2: Xét phần tử thứ hai (tại vị trí 2) Bước 2: Xét phần tử thứ hai (tại vị trí 2)

15 15
10 9 10 9
5 7 7 5
1 3 2 1 3 2
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

18 20

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 2: Xét phần tử thứ hai (tại vị trí 2) Bước 3: Xét phần tử thứ ba (tại vị trí 3)

15 15
10 9 10 9
7 5 7 5
1 3 2 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

21 23

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 2: Xét phần tử thứ hai (tại vị trí 2) Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Kết thúc
bước 2
15 15
10 9 10 9
7 5 7 5
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

22 24

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 3: Xét phần tử thứ ba (tại vị trí 3) Bước 3: Xét phần tử thứ ba (tại vị trí 3)

15 15
10 9 10 9
7 5 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

25 27

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 3: Xét phần tử thứ ba (tại vị trí 3) Bước 3: Xét phần tử thứ ba (tại vị trí 3)

Kết thúc
bước 3
15 15
10 9 10 9
5 7 7 5
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

26 28

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 4: Xét phần tử thứ tư (tại vị trí 4) Bước 4: Xét phần tử thứ tư (tại vị trí 4)

15 15
10 9 10 9
7 5 7 5
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

29 31

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 4: Xét phần tử thứ tư (tại vị trí 4) Bước 4: Xét phần tử thứ tư (tại vị trí 4)

15 15
9 10 10 9
7 5 7 5
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

30 32

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 4: Xét phần tử thứ tư (tại vị trí 4) Bước 5: Xét phần tử thứ năm (tại vị trí 5)

Kết thúc
bước 4
15 15
10 9 9 10
5 7 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

33 35

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 5: Xét phần tử thứ năm (tại vị trí 5) Bước 5: Xét phần tử thứ năm (tại vị trí 5)

15 15
10 9 9 10
5 7 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

34 36

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 5: Xét phần tử thứ năm (tại vị trí 5) Bước 6: Xét phần tử thứ sáu (tại vị trí 6)

Kết thúc
bước 5
15 15
10 9 10 9
5 7 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

37 39

i j i j

Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 6: Xét phần tử thứ sáu (tại vị trí 6) Bước 6: Xét phần tử thứ sáu (tại vị trí 6)

Kết thúc
bước 6
15 15
10 9 9 10
5 7 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

38 40

i j i j
Đổi chổ trực tiếp – interchange sort Đổi chổ trực tiếp – interchange sort
Bước 7: Xét phần tử thứ bảy (tại vị trí 7) Hoàn tất sắp xếp

15 15
9 10 9 10
5 7 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

41 43

i j

Đổi chổ trực tiếp – interchange sort


Giải thuật
Bước 7: Xét phần tử thứ bảy (tại vị trí 7)  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
Kết thúc  Bước 3 :
bước 7 Trong khi j <= N thực hiện
Nếu a[j]<a[i]: Hoán vị a[i], a[j];
15 j = j+1;
9 10
5 7  Bước 4 : i = i+1;
1 2 3 Nếu i < N: Lặp lại Bước 2.
1 2 3 4 5 6 7 8 Ngược lại: Dừng.

42

i j
44
Cài đặt
 Ðánh giá giải thuật
void InterchangeSort(int a[]) 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
for (int i = 0; i<a.length-1; i++) 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 trong từng
for (int j =i+1; j < a.length; j++)
if(a[i]>a[j]) trường hợp như sau:
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
45 47

Chọn trực tiếp – Selection sort


Bài tập
Ý tưởng:
 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 Chọn phần tử nhỏ nhất trong N phần tử ban đầu,
dần:
đưa phần tử này về vị trí đúng là đầu dãy hiện
15 7 9 10 6 20
hành; lúc này dãy hiện hành chỉ còn N-1 phần tử
1 2 3 4 5 6
cần sắp xếp, bắt đầu từ vị trí thứ 2; lặp lại quá
 Cho biết tổng số phép hoán vị và trình trên cho dãy hiện hành... đến khi dãy hiện
 Cho biết tổng số phép gán
hành chỉ còn 1 phần tử
46 48
Chọn trực tiếp – selection sort
Chọn trực tiếp – Selection sort 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
vtmin
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ử? 15
10 9
5 7
3 1 2
1 2 3 4 5 6 7 8
51

49

Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Tìm vị trí phần tử nhỏ nhất? 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 Bước 2: So sánh giá trị tại vtmin với tất cả giá trị
số sau ? 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
5 nhỏ hơnthì
10 cập nhật lại vtmin
nên cập nhật
vtmin
15 vị trí min
10 9
5 7
3 1 2 15
1 2 3 4 5 6 7 8
10 9
5 7
3 1 2
50 52
1 2 3 4 5 6 7 8
Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Tìm vị trí phần tử nhỏ nhất? 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ị 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 tại vị trí còn lại (từ 2 đến 8), nếu có9phần
lớn hơn 3
tử nào
nhỏ hơn phần tử tại vtmin thìhơn
7 lớn cập5nhật lại vtmin nên không
nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmincập
nên không cập nhật vị trí min
vtmin vtmin
nhật vị trí min

15 15
10 9 10 9
5 7 5 7
3 1 2 3 1 2
53 55
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Tìm vị trí phần tử nhỏ nhất? 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ị Bước 2: So sánh
1 nhỏ giá3 trị tại vtmin với tất cả giá trị
hơn
tại vị trí còn lại (từ 2 đến 8), nếu có phần tử nào nên cập
tại vị trí còn nhật2 đến 8), nếu có phần tử nào
lại (từ
nhỏ hơn phần tử tại vtmin thì3cập nhỏnhật
hơn 5lại vtmin vị trí min
nhỏ hơn phần tử tại vtmin thì cập nhật lại vtmin
nên cập nhật
vtmin vtmin
vị trí min

15 15
10 9 10 9
5 7 5 7
3 1 2 3 1 2
54 56
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Tìm vị trí phần tử nhỏ nhất? Tìm vị trí phần tử nhỏ nhất?

Bước 2: So sánh
15 lớn hơn giá1 trị tại vtmin với tất cả giá trị
tại vị trí còn lại (từcập
nên không 2 đến 8), nếu có phần tử nào
nhỏ hơnnhật phầnvị trí
tử min
tại vtmin thì cập nhật lại vtmin
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ữ Java,
đầu vào là mảng số nguyên a, kích thước N?
15
10 9
5 7
3 1 2
57 59
1 2 3 4 5 6 7 8

Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Tìm vị trí phần tử nhỏ nhất? 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ị Giả sử cần tìm vị trí phần tử nhỏ nhất
tại vị trí còn lại 2(từ 2 đến 8), nếu có phần tử nào
lớn hơn 1 bắt đầu từ vị trí k cho trước (ví dụ đoạn
nhỏ hơn phầnnên tử tại vtmin
không cập thì cập nhật lại vtmin từ 3 đến 8) thì giải quyết như thế nào?
nhật vị trí min vtmin Hãy viết hàm cài đặt bằng ngôn ngữ Java?

15
10 9 15
5 7 10 9
3 2 7 8
1 1 3 2
58 60
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Bước 2: Xét phần tử thứ hai (vị trí 2)
Giả sử cần sắp xếp dãy số sau tăng dần • 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
15 15
10 9 9 10
5 7 5 7
3 2 1 1 3 2
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

61 63

Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Bước 1: Xét phần tử thứ nhất (vị trí 1) Bước 3: Xét phần tử thứ ba (vị trí 3)
• Tìm phần tử nhỏ nhất từ vị trí 1 đến 8 • 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 • Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min

min
min
15 15
10 9 9 10
5 7 7 5
3 2 1 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

62 64

i i
Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Bước 4: Xét phần tử thứ tư (vị trí 4) 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í 4 đến 8 • 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 • Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min
min
min

15 15
9 10 9 10
7 5 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

65 67

i i

Chọn trực tiếp – selection sort Chọn trực tiếp – selection sort
Bước 5: Xét phần tử thứ năm (vị trí 5) 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í 5 đến 8 • 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 • Hoán vị 2 phần tử tại vị trí đang xét với vị trí phần tử min
min
min

15 15
9 10 9 10
5 7 5 7
1 2 3 1 2 3
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

66 68

i i
Cài đặt 1
Chọn trực tiếp – selection sort public static void SelectionSort(int a[])
{
Kết thúc giải thuật - hoàn tất sắp xếp int vtmin;
Tìm vị trí min
for (int i=0; i<a.length-1 ; i++)
{ tính từ i đến N-1
vtmin = i;
for(int j = i+1; j <a.length ; j++)
15
9 10 {
5 7 if (a[j ] < a[vtmin])
1 2 3 vtmin=j;
1 2 3 4 5 6 7 8 }
HoanVi(a[vtmin], a[i]);
69 }
} 71

Cài đặt 2
Giải thuật int TimVTMin(int a[], int k) void SelectionSort(int a[])
{ {
Bước 1: i = 1;
int vtmin=k; int vtmin;
Bước 2: Tìm phần tử a[vtmin] nhỏ nhất trong
for(int i=k+1; i<a.length; i++) for (int i=0; i<a.length-1 ; i++)
dãy hiện hành từ a[i] đến a[N]
{ {
Bước 3: Hoán vị a[vtmin] và a[i] vtmin = TimVTMin(a, i);
if(a[i]<a[vtmin])
Bước 4: HoanVi(a[vtmin], a[i]);
vtmin=i;
i = i+1 }
}
}
Nếu i < N thì lặp lại Bước 2 return vtmin;
Ngược lại: Dừng. }
Sinh viên hãy cài đặt 2 giải thuật sắp xếp InterchangeSort và SelectionSort và tính số lần So
sánh, số lần Hoán vị, và thời gian thực hiện của 2 giải thuật này. Test trên 1 bộ dữ liệu, sau đó
nêu ra ý kiến nhận xét.

70 72
Bài tập nộp tại lớp, time: 30 minutes Nổi bọt – bubble sort

 Minh họa từng bước thực hiện của giải thuật Ý tưởng:
Selection Sort khi sắp dãy số sau tăng dần: 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
15 7 9 10 6 20 trong cặp phần tử đó về vị trí đúng đầu
1 2 3 4 5 6 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ý
 Cho biết tổng số phép gán tìm min và tổng thứ i sẽ có vị trí đầu dãy là i. Lặp lại xử
số phép hoán vị lý trên cho đến khi không còn cặp phần
tử nào để xét.
73 75

Ðánh giá giải thuật


Ðối với giải thuật chọn trực tiếp, có thể thấy 10 1
i
rằng ở lượt thứ i, bao giờ cũng cần (n-i) lần
so sánh để xác định phần tử nhỏ nhất hiện 5 2

hành. Số lượng phép so sánh này không phụ 7 3

thuộc vào tình trạng của dãy số ban đầu, do 3 4


vậy trong mọi trường hợp có thể kết luận :
9 5

2 6

15 7

j 1 8
76

74
i 1 1 1 1

10 2 2 2

5 3 i 3 3

7 4 10 4

3 5 5 5

9 6 7 6

2 7 9 7

j 15 8 j 15 8
77 79

1 1 1 1

i 2 2 2 2

10 3 3 3

5 4 i 5 4

7 5 10 5

3 6 7 6

9 7 9 7

j 15 8 j 15 8
78 80
1 1 1 1

2 2 2 2

3 3 3 3
Kết
5 4 5 4 thúc
i 7 5 7 5

10 6 9 6

9 7 i 10 7

j 15 8 15 8
81 83

Giải thuật
Bước 1: i = 1;
1 1 Bước 2: j = N; //---a.length
2 2
Trong khi (j > i) thực hiện:
Nếu a[j]<a[j-1]: Hoán vị a[j] và a[j-1]
3 3
j = j-1;
5 4
Bước 3:
7 5 i = i+1;
i 9 6 Nếu i = N: Dừng
10 7 Ngược lại: Lặp lại Bước 2.
15 8 Sinh viên hãy cài đặt 3 giải thuật sắp xếp InterchangeSort và SelectionSort và Bubble Sort và
j
82
tính số lần So sánh, thời gian thực hiện, và số lần Hoán vị của 3 giải thuật này. Test trên 1 bộ
dữ liệu, sau đó nêu ra ý kiến nhận xét.
84
Cài đặt
void BubbleSort(int a[]) Đánh giá giải thuật
{
 Trong mọi trường hợp, số phép so sánh là:
int i, j;
for (i = 0 ; i<a.length-1 ; i++) (n-1) + (n-2) + … + 1 = n(n-1)/2 = O(n2)
{
for (j =a.length-1; j >i ; j --)  Số phép hoán vị:
{
if(a[j]< a[j-1])  Trường hợp xấu nhất: n(n-1)/2
HoanVi(a[j],a[j-1]);  Trường hợp tốt nhất: 0
}
}
} 85 87

Cài đặt
public static void HoanVi(int x, int y) 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
 Nổi bọt – Bubble Sort
 Chèn trực tiếp – Insertion Sort
 Quick Sort

86 88
Chèn trực tiếp – insertion sort Chèn trực tiếp – insertion sort
Giả sử cần sắp xếp dãy số sau tăng dần
Ý tưởng
Cho dãy ban đầu a1 , a2 ,... ,an

a1 a2 a3 a4 … an
15
1. Đã có đoạn gồm một phần tử a1 được sắp 10 9
5 7
3 2 1
a1 a2 a3 a4 … an
1 2 3 4 5 6 7 8

91

89

Chèn trực tiếp – insertion sort Insertion sort


Xem như phần tử thứ 1 đã có thứ tự

 Sau đó thêm a2 vào đoạn a1 sẽ có đoạn a1 a2 được sắp Tìm vị trí thích hợp để chèn
cho phần tử thứ 2

a1 a2 a3 a4 … an

 Tiếp tục thêm a3 vào đoạn a1 a2 để có đoạn a1 a2 a3


được sắp;

a1 a2 a3 a4 … an i=
15 ?
 Tiếp tục cho đến khi thêm xong aN vào đoạn a1 a2 10 9
5 7
...aN-1 sẽ có dãy a1 a2 .... aN được sắp. 3 2 1
a1 a2 a3 a4 … an 90
1 2 3 4 5 6 7 8 92
Insertion sort Insertion sort
Hai phần tử đầu tiên đã có thứ tự Bốn phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho Tìm vị trí thích hợp để chèn cho
phần tử thứ 3 phần tử thứ 5

i= i=
15 ? 15 ?
10 9 10 9
5 7 5 7
3 2 1 3 2 1
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
93 95

Insertion sort Insertion sort


Ba phần tử đầu tiên đã có thứ tự Năm phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho Tìm vị trí thích hợp để chèn cho
phần tử thứ 4 phần tử thứ 6

i= i=
15 ? 15 ?
10 9 9 10
5 7 5 7
3 2 1 3 2 1
1 2 3 4 5 6 7 8 94
1 2 3 4 5 6 7 8 96
Insertion sort Chèn trực tiếp – insertion sort
Sáu phần tử đầu tiên đã có thứ tự Kết thúc giải thuật
Tìm vị trí thích hợp để chèn cho
phần tử thứ 7

15
9 10
i= 5 7
15 1 2 3
9 10 ? 1 2 3 4 5 6 7 8
5 7
2 3 1 99

1 2 3 4 5 6 7 8
97

Insertion sort Chèn trực tiếp – insertion sort


Bảy phần tử đầu tiên đã có thứ tự
Tìm vị trí thích hợp để chèn cho
phần tử thứ 8 Chèn một phần tử x vào vị trí k của
mảng 1 chiều

Hãy viết hàm (C) chèn x vào vị trí k của dãy a

i=
15 ?
9 10
5 7
2 3 1
1 2 3 4 5 6 7 8 100
98
public static void InsertionSort(int a[])
Chèn trực tiếp – insertion sort {
int pos, x;
for(int i=1 ; i<=a.length ; i++) //đoạn a[0] đã sắp
Dựa vào đâu để xác định được vị {
trí chèn thích hợp của một giá trị x = a[i];
trong dãy có giá trị tăng dần? pos = i-1;
while((pos >= 0)&&(a[pos] > x))
Hãy viết hàm chèn x vào dãy a tăng dần sao {
cho dãy a thu được cũng tăng dần a[pos+1] = a[pos];
pos--;
}
a[pos+1] = x; //chèn x vào dãy
}
}

101 103

Mô tả giải thuật bằng mã tự nhiên Bài tập


Bước 1: i = 2; // giả sử có đoạn a[1] đã được sắp
Bước 2: x = a[i];  Minh họa từng bước thực hiện
Tìm vị trí pos thích hợp trong đoạn [1..i] để chèn khi áp dụng giải thuật Insertion Sort
a[i] vào để sắp xếp dãy số sau tăng dần
Bước 3: Dời chổ các phần tử từ pos đến i-1 sang
Lặp

phải 1 vị trí để dành chổ cho a[i] 15 7 9 10 6 20


1 2 3 4 5 6
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.  Cho biết tổng số phép gán và số phép so sánh của
Ngược lại : Dừng. các phần tử trong dãy

102 104
Kết luận
Đánh giá giải thuật  “Chèn trực tiếp” và “Chọn trực tiếp” đều có chi
 Mỗi lần lặp:
phí cho trường hợp xấu nhất là O(n2) do đó,
So sánh tìm vị trí thích hợp pos
Dời chỗ phần tử sang phải 1 vị trí không thích hợp cho việc sắp xếp các mảng lớn
 Giải thuật thực hiện tất cả N-1 vòng lặp
 Dễ cài đặt, dễ kiểm lỗi
!!! Số lượng phép so sánh và dời chỗ này phụ thuộc vào  “Chèn trực tiếp” tốt hơn “Chọn trực tiếp”, nhất
tình trạng của dãy số ban đầu
là khi mảng đã có thứ tự sẵn
Trường hợp Số phép so sánh Số phép gán
Tốt nhất ??? ???  Cần có những giải thuật hiệu quả hơn cho
Xấu nhất ??? ???
105 việc sắp xếp các mảng lớn 107

Đánh giá giải thuật Các giải thuật sắp xếp cơ bản

Trường Số phép so sánh Số phép gán


hợp  Đổi chỗ trực tiếp – Interchange Sort
 Chọn trực tiếp – Selection Sort
Tốt nhất
 Nổi bọt – Bubble Sort
 Chèn trực tiếp – Insertion Sort
Xấu nhất
 Quick Sort

106 108
QuikSort(a, 1, a.length);
QuikSort(a, 0, a.length-1);

Quick sort

 Chia dãy cần sắp thành 2 phần i=1, j=8

 Cách “chia”: ½ dãy bên trái chứa các giá trị L x R

nhỏ hơn ½ dãy bên phải


10 5 7 3 9 2 15 1
 Thực hiện việc sắp xếp trên từng dãy con (đệ
1 2 3 4 5 6 7 8
qui)
i j

<x x >x L=1


R=8
(x là phần tử trong dãy) Đoạn cần sắp xếp
Đoạn 1 Đoạn 2

L=1 L=4
109 111
R=3 R=8

Quick sort

Ví dụ: i=4, j=8

- Cho dãy số: 3; 5; 8; 10; 31; 4; 81; 7; 15; 17; 1 L x R

- Giả sử x = 10 thì sẽ có 2 phần như sau:


1 2 3 7 9 5 15 10
 Phần nhỏ hơn x: 3; 5; 8; 4; 7; 1 1 2 3 4 5 6 7 8

 Phần lớn hơn x: 31; 81; 15; 17 L=4


R=8 i j
L=1
R=3
Đoạn 1 Đoạn 2
Đoạn cần sắp xếp
L=4 L=5
110 R=5 R=8
112
i=5, j=8

L x R x
i=6, j=7

L R
1 2 3 5 9 7 15 10
L=5 L=6
1 2 3 4 5 6 7 8
R=8 R=7 1 2 3 5 7 9 10 15
L=4 L=4
R=5 i j R=5 1 2 3 4 5 6 7 8
L=1 L=1
R=4 R=4 i j
Đoạn 2
Đoạn cần sắp xếp Đoạn cần sắp xếp
L=6
R=8
113

i=6, j=8

L x R x
i=4, j=5

L R
1 2 3 5 7 9 15 10
L=6
1 2 3 4 5 6 7 8
R=8 1 2 3 5 7 9 10 15
L=4 L=4
R=5 i j R=5 1 2 3 4 5 6 7 8
L=1 L=1
R=4 R=4 i j
Đoạn 1
Đoạn cần sắp xếp Đoạn cần sắp xếp
L=6 116

R=7
114
i=1, j=4

L x R 2 3
1 5 7 9 10 15

1 2 3 4 5 6 7 8
1 2 3 5 7 9 10 15

1 2 3 4 5 6 7 8

Không còn đoạn


i j
nào cần sắp xếp!
L=1
R=4 Kết thúc
Đoạn 2
Đoạn cần sắp xếp Đoạn cần sắp xếp 119
L=3
R=4
117

Giải thuật
Cho dãy aL, aL+1, … aR
Bước 1:
x
i=3, j=4 Phân hoạch dãy aL … aR thành các dãy con:
L R  Dãy con 1: aL … aj < x
 Dãy con 2: aj+1 … ai-1 =x
2 3
1 5 7 9 10 15
 Dãy con 3: ai … aR > x
1 2 3 4 5 6 7 8
Bước 2:
L=3
R=4
i j  Nếu (L<j) Phân hoạch dãy aL … aj
 Nếu (i<R) Phân hoạch dãy ai … aR
Đoạn cần sắp xếp
118

120
Giải thuật phân hoạch dãy aL, aL+1, … aR thành 2 dãy con
Bước 1.1:
Bài tập
Chọn tùy ý một phần tử a[k] trong dãy, L≤k≤R
x=a[k], i=L, j=R
Minh họa từng bước thực hiện của giải thuật
Bước 1.2: Quick Sort khi sắp dãy số sau tăng dần:
Phát hiện và hiệu chỉnh cặp a[i] và a[j] nằm sai chỗ:
15 7 9 10 6 20 6 9 12 30
Bước 1.2a: Trong khi (a[i]<x) i++ 1 2 3 4 5 6 7 8 9 10
Bước 1.2b: Trong khi (a[j]>x) j--
Bước 1.2c: Nếu (i≤j): Hoán vị a[i] và a[j]; i++, j--
Bước 1.3:
Nếu i<j: Lặp lại bước 1.2
Ngược lại: Dừng phân hoạch
121 123

Cài đặt
void QuickSort(int a[], int left, int right)
{ int i, j, x;
Đánh giá giải thuật
x=a[(left+right)/2];
i=left; j=right;  Chi phí trung bình O(n*log2n)
do{
while(a[i]<x) i++;  Chi phí cho trường hợp xấu nhất O(n2)
while(a[j]>x) j--;  Chi phí tùy thuộc vào cách chọn phần tử
if(i<=j) “trục”:
{
 Nếu chọn được phần tử có giá trị trung bình,
HoanVi(a[i], a[j]); i++; j--;
}
ta sẽ chia thành 2 dãy bằng nhau;
}while(i<j);  Nếu chọn nhằm phần tử nhỏ nhất (hay lớn
if(left<j) QuickSort(a, left, j); nhất)  O(n2)
if(i<right) QuickSort(a, i, right);
} 122 124

You might also like