快速排序 以及数组第k大的应用

时间复杂度为:平均为nlog(n),最坏为n²,但很难达到最坏情况

空间复杂度为:O(1),不需要辅助数组,归并排序需要一个O(n)的辅助数组

快速排序第一种写法:

#include<bits/stdc++.h>
using namespace std;
int n, a[100005];
void quickSort(int *a, int l, int r){
    if(l >= r)
        return ;
    int mid = a[(l+r)/2];
    int left = l, right = r;
    while(true){
        //因为基准取得是(l+r)/2,所以不需要限制right和left的边界条件
        //所有不需要 right >= l 和 left <= r
        while(mid < a[right]){
            --right;
        }
        while(mid > a[left]){
            ++left;
        }
        if(left > right){
            break;
        }
        swap(a[left], a[right]);
        ++left;
        --right;
    }
    quickSort(a, l, right);
    quickSort(a, left, r);
    return ;
}
int main(){
    scanf("%d", &n);
    for(int i=1; i<=n; ++i){
        scanf("%d", &a[i]);
    }
    quickSort(a, 1, n);
    for(int i=1; i<=n; ++i){
        printf("%d ",a[i]);
    }
    return 0;
}

快速排序的第二种写法:

#include<bits/stdc++.h>
using namespace std;
int a[100005], n;
void quickSort(int *a, int l, int r){
    if(l >= r){
        return ;
    }
    //随机取基准,将a[l]作为基准
    swap(a[l], a[l+rand()%(r-l+1)]);
    int i = l+1, j = r, mid = a[l];
    while(true){
        while(j >= l+1 && mid < a[j]) --j;
        while(i <= r && mid > a[i]) ++i;
        if(i > j){
            break;
        }
        swap(a[i], a[j]);
        ++i;
        --j;
    }
    //保证当前区间的第j个元素的位置是一定正确的,
    //也就是基准所在位置一定正确
    //因为基准前面和后面的元素一定都小于等于基准
    swap(a[l], a[j]);
    quickSort(a, l, j-1);
    quickSort(a, j+1, r);
    return ;
}
int main(){
    scanf("%d", &n);
    for(int i=1; i<=n; ++i){
        scanf("%d", &a[i]);
    }
    quickSort(a, 1, n);
    for(int i=1; i<=n; ++i){
        printf("%d ",a[i]);
    }
    return 0;
}

应用:
数组第k大:

#include<bits/stdc++.h>
using namespace std;
int getKthNum(vector<int> &a, int l, int r, int k){
	swap(a[l], a[l+rand()%(r-l+1)]);
    int i=l+1, j=r, mid = a[l];
    while(true){
        //降序
        while(j >= l+1 && a[j] < mid) --j;
        while(i <= r && a[i] > mid) ++i;
        if(i>j){
            break;
        }
        swap(a[i], a[j]);
        ++i;
        --j;
    }
    swap(a[l], a[j]); //这个交换保证了在[l, r]中第k大在第k位上
    if(j+1 == k){
        return a[j];
    }
    else if(j+1 > k){
        return getKthNum(a, l, j-1, k);
    }
    else{
        return getKthNum(a, j+1, r, k);
    }
}
int main(){
    vector<int> a = {1,3,5,2,2};
    cout<<getKthNum(a, 0, a.size()-1, 3);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值