线性时间查找中位数算法

文章转自http://blog.csdn.net/z690933166/article/details/20844635
一、以期望线性时间做选择
一般来说,中位数的查找算法都是基于先排序,后找中间位置的数字的算法,但是因为线性时间排序所收到的限制比较大,而如果使用基于比较的排序,时间复杂度将至少为O(nlogn),如何以线性时间完成中位数或者数组中第N大元素的查找呢?
快速排序算法在每一次局部递归后都保证某个元素左侧的元素都比他小,右侧的元素都比她大,因此,可以利用这个思路快速找到第N大元素,而与快速排序算法不同的是,我们关注的并不是元素的左右两边,而仅仅是某一边,这样,可以证明,算法是线性时间复杂度的
二、程序代码

#include <stdio.h>  
void exch (int *array, int i, int j)  
{  
    if (i!=j)  
    {  
        array[i] ^= array[j];  
        array[j] = array[i] ^ array[j];  
        array[i] ^= array[j];  
    }  
}  

double select_middle (int *array, int beg, int end, int n)  
{  
    if (n == 1)  
        return array[1];  
    int i = beg, j;  
    for (j=i+1; j<=end; ++j)  
        if (array[j]<=array[beg])  
        {  
            ++i;  
            exch (array, i, j);  
        }  
    exch (array, beg, i);  

    if (i < n/2)  
        return select_middle (array, i+1, end, n);  
    else if (i > n/2)  
        return select_middle (array, beg, i-1, n);  
    else  
    {  
        if (n%2)  
            return array[i];  
        else  
        {  
            int j, m=array[0];  
            for (j=1; j<i; ++j)  
                if (array[j] > m)  
                    m=array[j];  
            return (double)(array[i]+m)/2;  
        }  
    }  
}  

int main ()  
{  
    int n=0;  
    int array[256];  
    printf ("Please input numbers, end by 9999:\n");  
    while (1)  
    {  
        scanf ("%d", &array[n]);  
        if (array[n] == 9999)  
            break;  
        ++n;  
    }  
    printf ("%lf\n", select_middle(array, 0, n-1, n));  
    return 0;  
}  

三、改进
在特殊情况下(完全逆序),这个算法的时间复杂度将不会是线性的,这是什么他原因造成的呢?这是因为在递归过程中,每一次选择的基准元素都是首个元素,即使使用随机化的算法,依然很有可能选择以非常大或者非常小的元素作为基准
解决方法是,先对整个数组划分为若干小组,再对每个小组进行排序,选择出中位数,再在已经选出的N个中位数中找出他们的中位数,这个最终的中位数就是十分接近中间的数字,以这个数为基准的话,就可以保证在最坏情况下,算法依然以线性时间运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值