五:寻找最小的k个数

通过全部排序O(nlogn),部分排序O(nk),用堆代替数组O(nlogk)都可以完成

还可以通过线性选择算法:O(n)

       选取数组S中一个元素作为主元(pivot)v,将集合S-{v}分割成Sa和Sb,就像快速排序那样:

       1)如果k <= |Sa|,那么第k个最小的元素必然在Sa中,这时,返回QuickSelect(Sa,k);

       2)如果k=1+|Sa|,那么主元就是第k个最小元素,即找到,直接返回它;

       3)否则,这第k个最小元素就在Sb中,即Sb中的第k-|Sa|-1个最小元素,我们递归调用QuickSelect(Sb,k-|Sa-1|)并返回。

// QuickSelect将第k小的元素放在S[k-1]
void QuickSelect(int S[], int k, int left, int right)
{
    int i,j;
    int pivot;
    if (left <= right)
    {
        pivot = median3(S, left, right);
        // 取3个数的中值作为主元,可以很大程度上避免最坏情况
        i = left;
        j = right - 1;
        for (;;)
        {
            while (S[++i] < pivot){}
            while (S[--j] > pivot){}
            if (i < j)
            {
                swap(S[i], S[j]);
            }
            else
            {
                break;
            }
        }
        // 重置主元
        swap(S[i], S[right - 1]);
        if (k <= i)
        {
            QuickSelect(S, k, left, i - 1);
        }
        else if(k > i + 1)
        {
            QuickSelect(S, k, i + 1, right);
        }
    }
    else
    {
        // 如果left > right, 利用插入排序调整一下
        InsertSort(S + left, right - left + 1);
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值