以期望线性时间选择第i小的元素(9.2)

1.理论

利用分治算法,即RANDDOMIZED-SELECT算法,这个算法是以7.2中的快速排序算法随机化版本为基础,将对输入数组进行递归划分,但和快速排序不同的是,快速排序会递归处理划分的两边,但RANDDOMIZED-SELECT只处理划分的一边。

伪算法:


       在算法第3行的RANDOMIZED-PARTITION执行之后,数组A[p..r]被划分成两个(可能空的)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一个元素都小于或者等于A[q],进而小于A[q+1..r]中的每一个元素,与快速排序一样,称A[q]为主元素。RANDDOMIZED-SELECT的第4行计算数组A[p..q]内的元素个数k,即处于划分低区的元素的个数加上一个主元素。然后第5行检查A[q]是不是第i小的元素。如果是,就返回A[q]。否则,算法要确定第i小的元素落在两个子数组中A[p..q-1和A[q+1..r]中的哪一个中。如果是i<k,则要找的元素落在划分的高区子数组中,因为我们已经知道了有k个值(即A[p..q]中的所有元素)小鱼A[p..r]中的第i个元素,故所求元素必是A[q+1..r]中的第(i-k)小元素,它在第9行中被递归的选取。

2.C代码

/*************************************************************************
	> File Name: randomIzedSelect.c
	> Author: NULL
	> Mail: 574889524@qq.com
	> Created Time: 2014年11月02日 星期日 15时05分07秒
 ************************************************************************/

#include<stdio.h>
#include <stdlib.h>  
#include <time.h>  
#define ARRSIZE 8  
/****************************************/
void ExChangeInt(int *a,int *b)      
{      
    int iTemp = *a;      
    *a = *b;      
    *b = iTemp;      
}     
/****************************************/
/*快速排序核心代码*/
int Partition(int *A,int p,int r)    
{    
    int j,x,i;    
    x = A[r];    
    i = p - 1;    
    for(j = p;j<=r-1;j++){    
        if(A[j] <=x){    
            i++;    
            ExChangeInt(&A[i],&A[j]);    
        }    
    }    
    ExChangeInt(&A[i+1],&A[r]);    
    return i + 1;    
}    
/*快排的随机主元素生成*/
int RandomIzedPartition(int *A,int p,int r)  
{  
    int i;  
    srand((unsigned)time(NULL));  
    i =rand()%(r-p+1)+p;  
    ExChangeInt(&A[r],&A[i]);  
    return Partition(A,p,r);  
}  
/****************************************/
/*以期望线性时间选择第i小的元素
*pArr:查找的对象数组
*p:查找的起始位置
*r:查找的结束位置
*i:查找在区间[p,r]中第i小的元素
*/
int RandomIzedSelect(int *pArr,int p,int r,int i)
{
    int k,q;
    if(p==r)
        return pArr[p];

    q = RandomIzedPartition(pArr,p,r);/*得到主元素的下标*/
    k=q-p+1;/*计算划分低区的元素个素*/
    if(k == i)/*说明找到了第i小的元素*/
        return pArr[q];
    
    if(i<k)
        return RandomIzedSelect(pArr,p,q-1,i);
    else
        return RandomIzedSelect(pArr,q+1,r,i-k);
}
/****************************************/
int main()
{
    int Arr[ARRSIZE] = {1,2,3,4,5,6,7,8};
    printf("i = %d\n",RandomIzedSelect(Arr,0,7,2));
    printf("i = %d\n",RandomIzedSelect(Arr,1,7,2));
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byd yes

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值