关于快速排序, 网上有各种教程, 就不细说.
思路就是:
找到一个基准数, 然后把小于这个数的数它放在左边, 把大于它的数放在它右边. 然后分治地解决左边和右边的排序.
一般基准有左边第一个数, 中间数, 随机某个数. 在不同的问题下, 选定不同的基准数实际时间复杂度可能会有极大差别, 理论上, 推荐随机的基准数.
实现快速排序的具体方式也有很多种, 但是基本的思路就是上面介绍的.
AC代码是以中间数为基准数, 而之前的以左边第一个数为基准数的代码都只通过了60%的样例.
下面是代码:
#include <iostream>
using namespace std;
void quickSort(int *a, int l, int r)
{
int x = l, y = r, mid = a[(l + r) >> 1];
do {
while(a[x] < mid) x++;
while(a[y] > mid) y--;
if(x <= y) {
swap(a[x], a[y]);
x++, y--;
}
} while(x <= y);
if(x < r) quickSort(a, x, r);
if(y > l) quickSort(a, l, y);
}
int main()
{
int n;
cin >> n;
int *a = new int[n+1];
for(int i = 0; i < n; ++i) {
cin >> a[i];
}
quickSort(a, 0, n - 1);
for(int i = 0; i < n; ++i) {
cout << a[i] << ' ';
}
cout << endl;
}
样例:
10
6 1 2 7 9 3 4 5 10 8
7
4 7 3 1 4 8 6
7
9 4 7 3 1 4 8 6
其实快排的代码算是挺短的, 但是在实际的过程中出现了很多难以预料的错误.
有的程序出不来, 有的没有排序排错了.
需要注意的是, 代码中有很多while循环, 对它们的功能要有很清晰的理解. 还有很多类似<, <= 这类的情况, 也要非常注意. 这些地方都非常容易出错.
以下是以左边第一个数为基准的情况
//以最左边为基准数
#include <iostream>
#include <algorithm>
using namespace std;
void quickSort(int *a, int left, int right)
{
if(right < left) return;
int key = a[left], l = left, r = right;
while(l < r) {
while(a[r] >= key && l < r) r--;
while(a[l] <= key && l < r) l++;
if(l < r) swap(a[l], a[r]);
}
swap(a[left], a[l]);
quickSort(a, left, l - 1);
quickSort(a, l + 1, right);
}
int main()
{
std::ios::sync_with_stdio(false);
int n;
cin >> n;
int *a = new int [n+1];
for(int i = 0; i < n; ++i) {
cin >> a[i];
}
quickSort(a, 0, n - 1);
for(int i = 0; i < n; ++i) {
cout << a[i] << ' ';
}
}
总之, 孰能生巧. 对于我这种蒟蒻来说, 要轻松的写好快排, 还是要多加练习, 让手把快排背下来.
刚才六分钟手打了一个快排, 零调试, 零bug(偷笑