详解快速排序
快速排序:又称为划分交换排序。是双冒泡,即对冒泡排序的改进。优点是在单线程进程里排序速度比较快,缺点是当排序文件记录已经有序或者基本有序时,该排序会逐渐退化为冒泡排序,使得时间复杂度为O(n^2)(有关时间复杂度可以参照之前的文章),另一个缺点是不稳定。
基本思想:在无序区间arr[left,right]中任取一个记录作为排序基准,可以假设为区间最左端的left,保存为临时值,然后用此基准划分区间arr1[left,i-1]和arr2[i+1,right],使得arr1的所有的值小于等于基准值,arr2的所有的值大于等于基准值,称为一趟排序。继续对两个区间进行划分,使得区间为空则停止划分。
演示代码:
- 方法一(以左边为基准)
void show(int *arr, int n) {
printf("\n状态");
for (int i = 0; i < n; i++) {
printf("%3d", arr[i]);
}
}
//做一次划分
int partition(int *arr, int i, int j) {
int tmp = arr[i];
while (i < j) {
while (arr[j] >= tmp&&i < j)j--;
if (i < j) {
arr[i] = arr[j];
i++;
}
while (arr[i] <= tmp&&i < j)i++;
if (i < j) {
arr[j] = arr[i];
j--;
}
}
arr[i] = tmp;
return i;
}
void quickSort3(int *arr, int left, int right) {
int p = 0;
if (left < right) {
p = partition(arr, left, right);
quickSort3(arr, left, p - 1);
quickSort3(arr, p + 1, right);
}
}
void main() {
int arr[10] = { 10,9,20,19,13,8,9,22,0,91 };
quickSort3(arr, 0, 9);
show(arr, 10);
system("pause");
}
测试结果:
- 方法二(以右边为基准)
void swap(int *i, int *j) {
int tmp = *i;
*i = *j;
*j = tmp;
}
void quickSort2(int *arr, int iLeft, int iRight) {
int i = iLeft - 1;
int j = iRight;
while (i < j) {
do {
do {
j--;
} while (arr[j] > arr[iRight] && j >= iLeft);
do {
i++;
} while (arr[i] < arr[iRight] && i < iRight);
if (i < j)swap(&arr[i], &arr[j]);
} while (i < j);
swap(&arr[i], &arr[iRight]);
quickSort2(arr, iLeft, i - 1);
quickSort2(arr, i + 1, iRight);
}
}
void main() {
int arr[10] = { 10,9,20,19,13,8,9,22,0,91 };
quickSort2(arr, 0, 9);
show(arr, 10);
system("pause");
}
测试结果同上。
大家认为哪种方法好呢?