快速排序算法

快速排序(Quicksort)算法

这个排序算法在面试题中基础遇到
虽然STL中有sort函数(自行了解)可以快速解决,
时间复杂度也相差无几,但是有些题目还是可以卡死sort排序。

如:求n个数第k大值(1<n<=1e8)

这个题目用sort是无法在一秒钟解决的。
当然用快速排序也无法解决,但是稍微改变一下就能解决。

所以今天我们来了解一下快速排序算法。

快速排序算法的时间复杂度为:
- 平均O(nlogn)
- 最差O(N2)

快速排序算法的大致过程
快速算法是基于递归实现,先确定一个基准数(假设取中间位置的数x=a[(l+r)/2])。
定义两个指针(i,j)i从头开始,j从尾开始。

在这里插入图片描述

当a[i]大于x时停止,当a[j]小于x时停止,判断当前i是否小于j,如果是就交换位置。
以此类推,当i>=j时退出循环。

在这里插入图片描述
在这里插入图片描述

此时的状态为

在这里插入图片描述

我们再分为两边进行递归处理,处理过程也是和上面一样。
因为经过以上操作左、右两边区间的数虽然排序不同,但是他们所在的区间已经不会改变

在这里插入图片描述

代码实现过程如下

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7;
int a[N];
void quick_sort(int l,int r){
    if(l>=r)return ;
    int i=l-1,j=r+1,mid=a[(l+r)/2];//指定两个指针i,j,和基准数mid
    while(i<j){//这里如上所说的操作
        while(a[++i]<mid);
        while(a[--j]>mid);
        if(i<j)swap(a[i],a[j]);
    };
    quick_sort(l,j);//递归左边处理
    quick_sort(j+1,r);//递归右边处理
}
int main{
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    quick_sort(0,n-1);
    for(int i=0;i<n;i++){
        cout<<a[i]<<" ";
    }
    return 0;
}

 然而对于开头所说的例题(找第k大数),如果数据过大的是无法在1s内结束操作,
 因此对快速算法模板代码进行改动,时间复杂度可以优化到O(n)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
typedef long long LL;
namespace IO{
    inline LL read(){
        LL o=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){o=o*10+c-'0';c=getchar();}
        return o*f;
    }
}using namespace IO;
const int N=1e6+7;
int a[N];
int quick_sort_th(int l,int r,int k){
    if(l>=r)return a[l];//当l==r时,就返回当前数
    int i=l-1,j=r+1;
    int mid=a[l+r>>1];
    while(i<j){
        while(a[++i]<mid);
        while(a[--j]>mid);
        if(i<j)swap(a[i],a[j]);
    };
    if(k<=(j-l+1))return quick_sort_th(l,j,k);//要查找的第k大数在左边区间就只需要去左区间找
    else return quick_sort_th(j+1,r,k-(j-l+1));//要查找的第k大数在左边区间就只需要去右区间找,并且第k大的数在右区间的排名是k-左区间总数(j-l+1)
}
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    cout<<quick_sort_th(0,n-1,k)<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值