Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 23 Lần 7: First = 7 J: 8 9 10 M: 2 5 10 10 15 20 22 25 30 35 Lần 8: First = 8 J: 9 10 M: 2 5 10 10 15 20 22 25 30 35 Lần 9: First = 9 J: 10 M: 2 5 10 10 15 20 22 25 30 35 Sau 9 lần đi mảng M trở thành: M: 2 5 10 10 15 20 22 25 30 35 - Phân tích thuật toán: + Trong mọi trường hợp: Số phép gán: G = 0 Số phép so sánh: S = (N-1) + (N-2) + … + 1 = ½N(N-1) + Trong trường hợp tốt nhất: khi mảng ban đầu đã có thứ tự tăng Số phép hoán vò: Hmin = 0 + Trong trường hợp xấu nhất: khi mảng ban đầu đã có thứ tự giảm Số phép hoán vò: Hmin = (N-1) + (N-2) + … + 1 = ½N(N-1) + Số phép hoán vò trung bình: Havg = ¼N(N-1) - Nhận xét về thuật toán nổi bọt: + Thuật toán sắp xếp nổi bọt khá đơn giản, dễ hiểu và dễ cài đặt. + Trong thuật toán sắp xếp nổi bọt, mỗi lần đi từ cuối mảng về đầu mảng thì phần tử nhẹ được trồi lên rất nhanh trong khi đó phần tử nặng lại “chìm” xuống khá chậm chạp do không tận dụng được chiều đi xuống (chiều từ đầu mảng về cuối mảng). + Thuật toán nổi bọt không phát hiện ra được các đoạn phần tử nằm hai đầu của mảng đã nằm đúng vò trí để có thể giảm bớt quãng đường đi trong mỗi lần đi. b. Thuật toán sắp xếp dựa trên sự phân hoạch (Partitioning Sort): Thuật toán sắp xếp dựa trên sự phân hoạch còn được gọi là thuật toán sắp xếp nhanh (Quick Sort). - Tư tưởng: + Phân hoạch dãy M thành 03 dãy con có thứ tự tương đối thỏa mãn điều kiện: Dãy con thứ nhất (đầu dãy M) gồm các phần tử có giá trò nhỏ hơn giá trò trung bình của dãy M, Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m . Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 24 Dãy con thứ hai (giữa dãy M) gồm các phần tử có giá trò bằng giá trò trung bình của dãy M, Dãy con thứ ba (cuối dãy M) gồm các phần tử có giá trò lớn hơn giá trò trung bình của dãy M, + Nếu dãy con thứ nhất và dãy con thứ ba có nhiều hơn 01 phần tử thì chúng ta lại tiếp tục phân hoạch đệ quy các dãy con này. + Việc tìm giá trò trung bình của dãy M hoặc tìm kiếm phần tử trong M có giá trò bằng giá trò trung bình của dãy M rất khó khăn và mất thời gian. Trong thực tế, chúng ta chọn một phần tử bất kỳ (thường là phần tử đứng ở vò trí giữa) trong dãy các phần tử cần phân hoạch để làm giá trò cho các phần tử của dãy con thứ hai (dãy giữa) sau khi phân hoạch. Phần tử này còn được gọi là phần tử biên (boundary element). Các phần tử trong dãy con thứ nhất sẽ có giá trò nhỏ hơn giá trò phần tử biên và các phần tử trong dãy con thứ ba sẽ có giá trò lớn hơn giá trò phần tử biên. + Việc phân hoạch một dãy được thực hiện bằng cách tìm các cặp phần tử đứng ở hai dãy con hai bên phần tử giữa (dãy 1 và dãy 3) nhưng bò sai thứ tự (phần tử đứng ở dãy 1 có giá trò lớn hơn giá trò phần tử giữa và phần tử đứng ở dãy 3 có giá trò nhỏ hơn giá trò phần tử giữa) để đổi chỗ (hoán vò) cho nhau. - Thuật toán: B1: First = 1 B2: Last = N B3: IF (First ≥ Last) //Dãy con chỉ còn không quá 01 phần tử Thực hiện Bkt B4: X = M[(First+Last)/2] //Lấy giá trò phần tử giữa B5: I = First //Xuất phát từ đầu dãy 1 để tìm phần tử có giá trò > X B6: IF (M[I] > X) Thực hiện B8 B7: ELSE B7.1: I++ B7.2: Lặp lại B6 B8: J = Last //Xuất phát từ cuối dãy 3 để tìm phần tử có giá trò < X B9: IF (M[J] < X) Thực hiện B11 B10: ELSE B10.1: J B10.2: Lặp lại B9 B11: IF (I ≤ J) B11.1: Hoán_Vò(M[I], M[J]) B11.2: I++ B11.3: J B11.4: Lặp lại B6 B12: ELSE B12.1: Phân hoạch đệ quy dãy con từ phần tử thứ First đến phần tử thứ J B12.2: Phân hoạch đệ quy dãy con từ phần tử thứ I đến phần tử thứ Last Bkt: Kết thúc - Cài đặt thuật toán: Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m . Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 25 Hàm QuickSort có prototype như sau: void QuickSort(T M[], int N); Hàm thực hiện việc sắp xếp N phần tử có kiểu dữ liệu T trên mảng M theo thứ tự tăng dựa trên thuật toán sắp xếp nhanh. Hàm QuickSort sử dụng hàm phân hoạch đệ quy PartitionSort để thực hiện việc sắp xếp theo thứ tự tăng các phần tử của một dãy con giới hạn từ phần tử thứ First đến phần tử thứ Last trên mảng M. Hàm PartitionSort có prototype như sau: void PartitionSort(T M[], int First, int Last); Nội dung của các hàm như sau: void PartitionSort(T M[], int First, int Last) { if (First >= Last) return; T X = M[(First+Last)/2]; int I = First; int J = Last; do { while (M[I] < X) I++; while (M[J] > X) J ; if (I <= J) { Swap(M[I], M[J]); I++; J ; } } while (I <= J); PartitionSort(M, First, J); PartitionSort(M, I, Last); return; } //=========================================== void QuickSort(T M[], int N) { PartitionSort(M, 0, N-1); return; } - Ví dụ minh họa thuật toán: Giả sử ta cần sắp xếp mảng M có 10 phần tử sau (N = 10): M: 45 55 25 20 15 5 25 30 10 3 Ban đầu: First = 1 Last = 10 X = M[(1+10)/2] =M[5] = 15 First X = 15 Last M: 45 55 25 20 15 5 25 30 10 3 Phân hoạch: Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m . Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 26 I X = 15 J M: 45 55 25 20 15 5 25 30 10 3 I X = 15 J M: 3 55 25 20 15 5 25 30 10 45 I X = 15 J M: 3 10 25 20 15 5 25 30 55 45 I X = 15 M: 3 10 5 20 15 25 25 30 55 45 J First X = 15 I Last M: 3 10 5 15 20 25 25 30 55 45 J Phân hoạch các phần tử trong dãy con từ First -> J: First = 1 Last = J = 4 X = M[(1+4)/2] = M[2] = 10 First X = 10 Last M: 3 10 5 15 20 25 25 30 55 45 Phân hoạch: I X = 10 J M: 3 10 5 15 20 25 25 30 55 45 X = 10 J M: 3 10 5 15 20 25 25 30 55 45 I J X = 10 M: 3 5 10 15 20 25 25 30 55 45 I Phân hoạch các phần tử trong dãy con từ First -> J: First = 1 Last = J = 2 X = M[(1+2)/2] = M[1] = 3 First Last M: 3 5 10 15 20 25 25 30 55 45 X = 3 Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m . Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 27 Phân hoạch: I J M: 3 5 10 15 20 25 25 30 55 45 X = 3 I≡J M: 3 5 10 15 20 25 25 30 55 45 X = 3 J I M: 3 5 10 15 20 25 25 30 55 45 X = 3 First J I Last M: 3 5 10 15 20 25 25 30 55 45 Phân hoạch các phần tử trong dãy con từ I -> Last: First = I = 3 Last = 4 X = M[(3+4)/2] = M[3] = 10 First Last M: 3 5 10 15 20 25 25 30 55 45 X = 10 Phân hoạch: I J M: 3 5 10 15 20 25 25 30 55 45 X = 10 I≡J M: 3 5 10 15 20 25 25 30 55 45 X = 10 J I M: 3 5 10 15 20 25 25 30 55 45 X = 10 First J I Last M: 3 5 10 15 20 25 25 30 55 45 Phân hoạch các phần tử trong dãy con từ I -> Last: First = I = 5 Last = 10 X = M[(5+10)/2] = M[7] = 25 First X = 25 Last M: 3 5 10 15 20 25 25 30 55 45 Phân hoạch: Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m Click to buy NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m . . V i e w e r w w w . d o c u - t r a c k . c o m . Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 25 Hàm QuickSort có prototype như sau: void QuickSort(T M[], int N); Hàm thực hiện việc sắp xếp N phần tử có kiểu dữ liệu T trên. NOW! P D F - X C h a n g e V i e w e r w w w . d o c u - t r a c k . c o m . Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 27 Phân hoạch: I J M: 3 5 10 15 20 25 25 30 55 45 X = 3 I≡J M:. Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 23 Lần 7: First = 7 J: 8 9 10 M: 2 5 10 10 15 20