快速排序,简称快排。
如大家所见,当我们要用C语言或者c++等编译语言将一堆数字进行排序的时候,其实并不复杂,我们只需要用两次for就可以将数字排好顺序,但这样排序的时间复杂度,大家应该都知道是n(n^2)的,在一些ac题目中,其实是可能会超时的,比如一道题的范围是0<N<10^9,那么这样排序我们最多要进行10^18次,显然这时肯定会超时的,所以这时候就要用到快排的思想。
首先,快排的时间复杂度是o(n)的,比起我们的常规方法,时间上是快很多的,所以才被称为快速排序。
下面是快排的中心思想——分治:
- 确定分界点x:q[l],q[r],q[(l+r)/2],或者任取一点
- 调整区间,小于等于x的放在x左边,大于x的放在x右边
- 递归将左边和右边分别排好序
之后是快排的核心内容——调整区间:
我们先来展示快排的暴力做法:
- 另建两个数组a[],b[]
- 对q[l]到q[r]扫描,小于等于x的丢到a,大于x的丢到b
- 先将a存进q,再接着存b
这个做法的时间复杂度和快排是一样的。
然后我们再看看快排优雅的做法:
- 在l处和r处设置一个“指针”i,j
- 如果i处小于等于x,则i右移,直到i处大于x停下;然后判断j处,如果j处大于x,则j左移,直到j处小于等于x停下
- 终止条件:i=j
最后,上代码!
void quick(int q[], int l, int r)
{
if (l >= r)
return;
int x = q[(l+r)/2], i = l - 1, j = r + 1;
while (i < j)
{
do i++;
while (q[i] < x);
do j–;
while (q[j] > x);
if (i < j)
swap(q[i], q[j]);
}
quick(q, l, j);
quick(q, j+1, r);
}
算法练习
Acwing785https://www.acwing.com/activity/content/problem/content/819/Acwing786
https://www.acwing.com/activity/content/problem/content/820/