快速选择

快速选择和快速排序类似,将数组分为S1和S2。当K值小于S1的的长度时,对S1进行递归。当k值刚好等于pivot时,那么已经找到了。当k值大于S1长度加一时,对S2进行递归。最后K始终在数组下标k-1的位置。

#include <iostream>
#include <vector>
using namespace std;

template <typename Comparable>
void insertionSort(vector<Comparable> &vec,int left ,int right)
{
    for(int p=left+1;p<=right;p++)
    {
        Comparable tmp=std::move(vec[p]);
        int j=p;
        for(;j>left&&tmp<vec[j-1];j--)
            vec[j]=std::move(vec[j-1]);

        vec[j]=std::move(tmp);
    }
}


//三位中值分割
template <typename Comparable>
const Comparable & median3(vector<Comparable> & a,int left,int right)
{
    int center=(left+right)/2;
    if(a[right]<a[left])
        std::swap(a[center], a[left]);
    if (a[right]<a[center])
        std::swap(a[right], a[center]);
    if(a[center]<a[left])
        std::swap(a[center], a[left]);

    std::swap(a[center], a[right-1]);
    return a[right-1];


}
template <typename Comparable>
void quickSelect(vector<Comparable> & a,int left,int right,int k)
{
    if(left+10<=right)  //当数量比较少时,使用插入排序效果较好
    {
        const Comparable & pivot=median3(a, left, right);
        int i=left;
        int j=right-1;

        for(;;)
        {

            while (a[++i]<pivot){}
            while (pivot<a[--j]){}
            if(i<j)
            {
                std::swap(a[i], a[j]);
            }
            else
            {
                break;
            }
        }
        std::swap(a[i], a[right-1]);

        if(k<=i)
        {
            quickSelect(a, left, i-1, k);
        }
        else if (k>i+1)
        {
            quickSelect(a, i+1,right,k);
        }


    }
    else
    {
        insertionSort(a,left,right);

    }

}

template <typename Comparable>
void quickSelect(vector<Comparable> & a,int k)
{
     quickSelect(a,0,a.size()-1,k);
}



int main(int argc, const char * argv[]) {
    // insert code here...
    vector<int> a{1,6,3,5,4,6,7,10,2,37,38,12,2,32,5,36,73,224,7,8,2,4,7,2,7,9,0,4,45,34,67,23,
    47,45,98,27,56};
    int k;
    cin>>k;
    cout<<endl;
    quickSelect(a, k);
    std::cout <<a[k-1]<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值