Quick Sort運用到Divide and Conquer的觀念,即是當我們把問題分到很小很小的時候,小問題相對容易解決,而每一個小問題解決之後,大問題也順勢被解決了。其中,把資料分成一半,一半再分成一半...的循環是很常見的。
Qucik Sort的方法是在原本資料中隨意取出一個element當作pivot,將所有小於此資料的elements放到pivot的左邊,大於者放到右邊,接著分別在左右邊的所有elements中另外各取一個pivot,遞迴地重複一樣的事情,直到分割出來的資料大小是零或是一後便不再分割,最後把所有被分割的資料依序組合起來,整個資料便會照順序排列了。
為了不使用額外的記憶體空間,實際撰寫程式處理單一問題(把小於pivot者放右邊、反之左邊,以下code中稱作partition)時,先把pivot放到最右邊,掃過左邊其餘的elements,發現第一個比pivot小的讓他跟左邊第一個element對換位置,發現第二個比pivot小的讓他跟左邊第二個element對換位置,以此類推下去。
#include <stdio.h>
// Function Declarations
void qsort(int *arr, int left, int right);
int partition(int *arr, int left, int right, int pivInd);
void swap(int *a, int *b);
void printArr(int *arr, int len);
/*
* Function : main
*/
int main(void){
int arr[8] = {6,5,2,3,8,1,7,4};
// print out original array
printArr(arr, sizeof(arr)/sizeof(arr[0]));
// qsort here
qsort(arr, 0, sizeof(arr)/sizeof(arr[0])-1);
// print out the array after sorting
printArr(arr, sizeof(arr)/sizeof(arr[0]));
return 0;
}
/*
* Function : qsort
* By using divide and conquer, we keep finding a pivot
* and make the elements which are smaller than it in
* front of the pivot.
*/
void qsort(int *arr, int left, int right){
if(right > left){
//divide
int pivInd = (right + left) / 2;
pivInd = partition(arr, left, right, pivInd);
//conquer
qsort(arr, left, pivInd-1);
qsort(arr, pivInd+1, right);
}
}
/*
* Function : partition
* Make the elements which are smaller than arr[pivInd] in
* front of the pivot. And return the index of the original
* arr[pivInd].
*/
int partition(int *arr, int left, int right, int pivInd){
// pivot value, store index
int pivVal = arr[pivInd];
int stoInd = left;
// swap the pivot and the last element
swap(&arr[pivInd], &arr[right]);
// scan through the arr from left to right-1
// make the elements which are smaller than pivVal in the font
int i;
for(i=left ; i<=(right-1) ; i++){
if(arr[i] < pivVal){
swap(&arr[stoInd++], &arr[i]);
}
}
// swap back the pivot and the last element
swap(&arr[stoInd], &arr[right]);
// return the index where the original arr[pivInd] stores
return stoInd;
}
/*
* Function : swap
* Swap to variables by passing two pointers.
*/
void swap(int *a, int *b){
int t;
t = *a;
*a = *b;
*b = t;
}
/*
* Function : printArr
* Print out the array
*/
void printArr(int *arr, int len){
while(len--)
printf("%d ",*arr++);
printf("\n");
}
然而,實際上C語言的stdlib.h中有qsort函式可以直接拿來用:
qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);
完整範例如下:
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b){
return ( *(int *)a - *(int *)b);
}
void printArr(int *arr, int len){
while(len--)
printf("%d ",*arr++);
printf("\n");
}
int main(void){
int arr[8] = {6,5,2,3,8,1,7,4};
int len = sizeof(arr)/sizeof(arr[0]);
printArr(arr, len);
// qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);
qsort(arr, len, sizeof(arr[0]), compare);
printArr(arr, len);
return 0;
}
參考資料:


