快排主要运用了分治策略,每次选一个主元(主元放在它最终的位置上,在它左边的数都比它小,在它右边的数都比它大),从两边往中间寻找,当左边的元素大于等于主元、右边的元素小于等于主元时停下来交换左右两个元素,直到左边界不再小于右边界;然后递归地处理主元左边和右边的数据~~
接下来有两个快排的写法:
第一种是每次选择左边第一个数作为主元的快排,未做任何优化:
int partition(int *A, int left, int right){
int pivot = A[left];
while(left < right){
while(left < right && A[right] > pivot)
right--;
A[left] = A[right];
while(left < right && A[left] <= pivot)
left++;
A[right] = A[left];
}
A[left] = pivot;
return left;
}
void qSort(int *A, int left, int right){
if(left < right){
int pos = partition(A, left, right);
qSort(A, left, pos - 1);
qSort(A, pos + 1, right);
}
}
void quickSort(int *A, int N){
qSort(A, 0, N-1);
}
第二种对主元的选择进行了优化,每次选择左边、中间和右边数据的中位数作为主元,同时将这三者排好序。需要注意递归的边界。
void swap(int &a, int &b){
int c = a;
a = b;
b = c;
}
int getPivot(int *A, int left, int right){
int center = (left + right) / 2;
if(A[left] > A[center])
swap(A[left], A[center]);
if(A[left] > A[right])
swap(A[left], A[right]);
if(A[center] > A[right])
swap(A[center], A[right]);
swap(A[center], A[right - 1]);
return A[right -1];
}
void qSort(int *A, int left, int right){
if(left >= right)
return;
int pivot = getPivot(A, left, right);
if(left + 1 == right) return;
int i = left, j = right -1;
while(1){
while(A[++i] < pivot);
while(A[--j] > pivot);
if(i < j)
swap(A[i], A[j]);
else
break;
}
swap(A[i], A[right - 1]);
qSort(A, left, i - 1);
qSort(A, i + 1, right);
}
void quickSort(int *A, int N){
qSort(A, 0, N-1);
}