快速排序
一、思想
快速排序是对冒泡排序的一种改进。它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
假设待排序的序列为{a[L],a[L+1],a[L+2],……,a[R]},首先任意选取一个记录(通常可选中间一个记作为枢轴或支点),然后重新排列其余记录,将所有关键字小于它的记录都放在左子序列中,所有关键字大于它的记录都放在右子序列中。由此可以将该“支点”记录所在的位置mid作分界线,将序列分割成两个子序列和。这个过程称作一趟快速排序。
一趟快速排序的具体做法是:附设两个指针i和j,它们的初值分别为L和R,设枢轴记录取mid,则首先从j所指位置起向前搜索找到第一个关键字小于的mid的记录,然后从i所指位置起向后搜索,找到第一个关键字大于mid的记录,将它们互相交换,重复这两步直至i>j为止。
快速排序的时间的复杂性是O(nlog2n),速度快,但它是不稳定的排序方法。就平均时间而言,快速排序是目前被认为是最好的一种内部排序方法
二、代码
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
long long a[300005];
void px(long long l, long long r) {
long long i = l, j = r;
long long mid = a[(l + r) / 2];
do {
while(a[i] < mid) i++;
while(a[j] > mid) j--;
if(i <= j) {
swap(a[i], a[j]);
i++;
j--;
}
} while (i <= j);
if(l < j) px(l, j);
if(i < r) px(i, r);
}
int main() {
long long n;
scanf("%lld", &n);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
px(1, n);
for(int i = 1; i <= n; i++) printf("%lld ", a[i]);
return 0;
}