算法实践系列--查找第K大值

下面的算法实现基于随机化快排,有一个前提是需要假设所有的元素都不相等,否则算法不成立。下面是具体实现:

1)随机划分算法与快排一样:

/// <summary>
/// 快速排序的分隔,即:对于一个指定的主元x,找到位置i,使得i的左边元素都小于等于x,右边都大于等于x.
/// </summary>
/// <param name="A"></param>
/// <param name="p"></param>
/// <param name="q"></param>
/// <returns></returns>
private int QuickSortPartion(int[] A, int p, int q)
{
count2++;
int theCount = q - p + 1;
//只有一个元素的情况,返回-1表示不用继续分割
if (theCount==1)
{

return -1;
}
//如果元素为2,则不用继续分割,只需要简单处理即可,这可以节省一些时间,但不是必须.
if (theCount == 2)
{
if (A[p] > A[q])
{
int tmp = A[p];
A[p] = A[q];
A[q] = tmp;
}
return -1;
}
//随机获取主元
Random theR=new Random(10);
int theMasterIndex = theR.Next(1, theCount);
int theMasterP = p + theMasterIndex -1;
//找到主元x,并与下界元素交换。
int theX = A[theMasterP];
A[theMasterP] = A[p];
A[p] = theX;
int i = p;
//寻找i,使得小于i位置的元素都小于等于thex,大于i位置的元素都大于thex.
for(int j=p+1;j<=q;j++)
{
if (A[j] <= theX)
{
i++;
int theTmp = A[j];
A[j] = A[i];
A[i] = theTmp;
}
count2++;
}
//将主元放到位置i.
A[p] = A[i];
A[i] = theX;
return i;
}

2)查找算法,与快排类似:

/// <summary>
/// 寻找序列中第K大的值.
/// </summary>
/// <param name="A">序列</param>
/// <param name="S">序列开始位置</param>
/// <param name="E">序列结束位置</param>
/// <param name="K">查找结果条件</param>
private int FindNOKValue(int[] A, int S, int E,int K)
{
count2++;
//先找划分位置i
int theDivI = QuickSortPartion(A, S, E);
//不需要划分,也表示没找到.
if (theDivI < 0)
{
return -1;
}
//查找跟快排的区别就是每次只需要进入一个分支。
//如果划分位置刚好是K,就表示第K大值找到.
if (theDivI == K)
{
return A[K];
}
//如果查找划分位置大于K,则进入小的划分,否则进入大的划分.
if (theDivI > K)
{
int theP1_S = S, theP1_E = theDivI - 1;
//对左边递归快排
if (theP1_E >= S)
{
return FindNOKValue(A, theP1_S, theP1_E,K);

}
}
else
{
int theP2_S = theDivI + 1, theP2_E = E;
//对右边递归快排.
if (theP2_S <= theP2_E)
{
return FindNOKValue(A, theP2_S, theP2_E,K);
}
}
return -1;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值