选择问题

本文深入探讨了快速选择算法,一种高效的查找未排序列表中第k小元素的方法。介绍了四种主要的实现策略,包括使用最小堆、最大堆、分治算法改进的快速排序,以及优化的枢纽元选择策略。详细解析了快速选择算法的步骤,提供了具体代码示例,展示了如何通过递归分割和选择枢纽元来加速搜索过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

选择问题是,在N个数中选择第k小的,有几种方法:

1.N个元素建立最小堆,k次deletemin,时间O(klogN)

2.k个元素建立最大堆,N次percdown,时间O(Nlogk)

3.使用分治算法,改进快速排序,每次解决两个子问题中的一个,平均时间O(N)

4.改进方法3中枢纽元的选择,使用五分化中项的中项或者七分化中项的中项,最坏时间O(N)

快速选择问题步骤:

1.若集合S中只有1个元素,那么返回,若使用了小数组的cutoff方法,那么直接插入排序并返回第k个最小元

2.选择一个枢纽元v

3.将S-\left [ v \right ]分割成S_{1}S_{2}

4.若k\leqslant \left | S_{1} \right |,那么第k个最小元在S_{1}中,返回quickselect(S_{1},k);若k= 1+ \left | S_{1} \right |,那么枢纽元就是第k个最小元;否则,k在S_{2}中,是S_{2}的第k- \left | S_{1} \right |-1个最小元,返回quickselect(S_{2}k- \left | S_{1} \right |-1)

代码如下:

/* 快速选择问题主例程,选择第k小的 */
void Qselect(int *a, int k, int left, int right)
{
    int i, j;
    int Pivot;

    if (left + cutoff <= right)
    {
        Pivot = Median3(a, left, right);;
        i = left, j = right - 1;

        for (;;)
        {
            while (a[++i] < Pivot);
            while (a[--j] > Pivot);
            if (i < j)
                Swap(&a[i], &a[j]);
            else
                break;
        }
        Swap(&a[i], &a[right - 1]);

        /* 这里和快速排序不同,因为只需要处理一个子问题 */
        if (k <= i)
            Qselect(a, k, left, i - 1);
        else if (k > i + 1)
            Qselect(a, k, i + 1, right);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值