前言
快速排序与归并排序都是两个很重要的排序算法。其平均时间复杂度都是nlogn。在数字很大的情况下,sort可能要超时。比如第k个数,逆序对问题。2333,这里必卡sort。
一、快排是什么?
快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
二、快排的思想步骤:
1.确定分界点,x= q【l+r>>1】;
2.交换调整区间,使前一个区间的数小于等于x,后一个区间是大于等于x;
3.用步骤1,2递归处理左右两个区间。
三、模板及其应用:
1.快排模板
代码如下(示例):
#include <iostream>
using namespace std;
const int N = 1000010;
int q[N];
void qsort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + 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]);
}
qsort(q, l, j); //这里或者改为qsort(q, l, i-1);和qsort(q, l, i);
qsort(q, j + 1, r);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
qsort(q, 0, n - 1);
for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
return 0;
}
2.第k个数
注意:其实第k个数就是考察会不会用快排来进行优化
题目链接
题目描述:给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。
输入样例:
5 3
2 4 1 5 3
输出样例:
3
AC代码
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
const int N =1e6+9;
int q[N];
void qsort(int l,int r,int k ){
if(l>=r) return;
int i = l-1,j= r+1,x=q[(r+l)>>1]; //注意指针在两边
while(i<j){
do i++ ;while(q[i]<x); //一旦相等就不用交换了
do j-- ;while(q[j]>x);
if(i < j) swap(q[i],q[j]);
}//两个指针不可穿过,也可以理解为相遇即停止,x就只是循环时用来作判断的
int n = j-l+1; //记录当层前面半函数作用的数组,一定要用j,避免出错!
if(k<=n) qsort(l,j,k); //优化; k是指第几个数
else qsort(j+1,r,k-n);
}
int main(){
int n ,k;
scanf("%d%d",&n,&k);
for(int i = 0;i <n;i++) scanf("%d",&q[i]);
qsort(0,n-1,k);
printf("%d",q[k-1]);
}
用j的原因是:划分区间,i左边的都是小于等于x的,右边都是大于等于x的
3.总结
附上各个排序的时间复杂度图
注:稳定性是指排序后,原本相等的两个数排序后会不会改变原来的顺序。
以后有必要的话,再把其他排序算法补全吧,(●’◡’●)。
图片:
但是sort 确实最快的!
STL sort,因为它是经过特殊设置的,在任何情况下都要比快速排序快。sort不是单纯的O(nlog n),而是无限接近于O(n)的。归并排序是比较接近于O(nlog n)的,会比下界为O(n^2)的快速排序稳定。