Phương pháp phân đoạn QuickSort

Một phần của tài liệu Giáo trình kỹ thuật lập trình 2 (Trang 79 - 83)

Đây là một phương pháp sắp xếp tốt do C.A.R Hoare đề xuất. Thuật tốn này cĩ tốc độ trung bình nhanh hơn các thuật tốn sắp xếp tổng quát khác. Do đĩ Hoare dùng chữ “Quick” để đặt tên cho thuật tốn này.

Ý tưởng chính: Để sắp dãy a[1] ... a[n], ta thực hiện sắp xếp dãy a từ chỉ số 1 đến chỉ số n. QuickSort dựa trên phân hoạch dãy ban đầu thành hai phần dựa vào giá trị x, x là giá trị của một phần tử tùy ý trong dãy ban đầu:

 Dãy thứ 1 : gồm các phần tử a[1]..a[i] cĩ giá trị khơng lớn hơn x.  Dãy thứ 2 : gồm các phần tử a[i]..a[n] cĩ giá trị khơng nhỏ hơn x. Sau khi phân hoạch thì dãy ban đầu được phân thành ba phần:

1. a[k] < x, với k = 1..i 2. a[k] = x, với k = i..j 3. a[k] > x, với k = j..n

a[k] < x a[k] = x a[k] > x

Ta cĩ nhận xét khi đĩ dãy con thứ 2 đã cĩ thứ tự, nếu dãy con 1 và dãy con 3 cĩ một phần tử thì chúng cũng đã cĩ thứ tự, khi đĩ dãy ban đầu đã được sắp. Ngược lại, nếu dãy con 1 và 3 cĩ nhiều hơn một phần tử thì dãy ban đầu cĩ thứ tự khi dãy con 1 và 3 được sắp. Để sắp xếp dãy con 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 vừa trình bày.

Giải thuật phân hoạch dãy a[left], a[left+1],.., a[right] thành hai dãy con:  Bước 1 : Chọn tùy ý một phần tử a[k] trong dãy là giá trị mốc, left ≤ k ≤ right,

o Cho x = a[k], i = left, j = right.

 Bước 2 : Tìm và hốn vị cặp phần tử a[i] và a[j] khơng đúng thứ tự đang sắp.

o Bước 2-1 : Trong khi a[i] < x ⇒ i++;

o Bước 2-2 : Trong khi a[j] > x ⇒ j--;

o Bước 2-3 : Nếu i < j ⇒ Swap(a[i], a[j]) // a[i], a[j] sai thứ tự  Bước 3 :

o Nếu i < j: ⇒ Bước 2; // chưa hết mảng dừng

o Nếu i ≥ j: ⇒ Dừng.

Giải thuật để sắp xếp dãy a[left], a[left+1],.., a[right]: được phát biểu theo cách đệ quy như sau:

 Bước 1 : Phân hoạch dãy a[left]...a[right] thành các dãy con:

o Dãy con 1: a[left]...a[j] < x

o Dãy con 2: a[j+1]...a[i-1] = x

o Dãy con 3: a[i]...a[right] > x  Bước 2 :

o Nếu (left < j) // dãy con 1 cĩ nhiều hơn 1 phần tử

 Phân hoạch dãy a[left]...a[j]

o Nếu (i < right) // dãy con 3 cĩ nhiều hơn 1 phần tử

 Phân hoạch dãy a[i]...a[right]

Ví dụ phân hoạch dãy sau: 10 3 7 6 2 5 4 16

Phân hoạch đoạn left = 1, right = 8, x = a[4] = 6

10 3 7 6 2 5 4 16

left = 1 right = 8

4 3 5 2 6 7 10 16

4 3 5 2 6 7 10 16

left = 1 right = 4

2 3 5 4 6 7 10 16 (adsbygoogle = window.adsbygoogle || []).push({});

Phân hoạch đoạn left = 3, right = 4, x = a[3] = 5

2 3 5 4 6 7 10 16

left = 3 right = 4

2 3 4 5 6 7 10 16

Phân hoạch đoạn left = 6, right = 8, x = a[7] = 10

2 3 4 5 6 7 10 16

left = 6 right = 8

2 3 4 5 6 7 10 16

QuickSort được cài đặt đệ quy như sau:

void QuickSort(int a[], int left, int right) {

int x;

x = a[(left+right)/2]; // chọn phần tử giữa làm gốc

i = left; j = right; do{

while (a[i] < x) i++; // lặp đến khi a[i] >= x while (a[j] > x) j--; // lặp đến khi a[i] <= x

if ( i <= j) // nếu cĩ 2 phần tử a[i] và a[j] ko theo thứ tự

{

Swap(a[i], a[j]);

i++; // qua phần tử kế tiếp

j--; // qua phần tử đứng trước

} } while (i<j);

if (left < j) // phân hoạch đoạn bên trái

QuickSort(a, left, j);

if (right > i) // phân hoạch đoạn bên phải QuickSort(a, i, right);

Một phần của tài liệu Giáo trình kỹ thuật lập trình 2 (Trang 79 - 83)