您的位置:首页 > 编程语言

线性时间查找第k大元素

2013-08-02 19:42 162 查看
/* 找出第k大的元素可以使用:堆排序,桶排序等方法,这里介绍一种O(n)的分治算法:先对数组划分,然后判断第k小的元素应该在哪个分组,再对相应的分组递归 */
int partion(int *a, int start, int end) {
int rnd = start + rand() % (end - start + 1);
int tmp = a[rnd];
a[rnd] = a[start]; //随机获取参考值
while (start < end) {
for (; start < end && a[end] > tmp; end--);
if (start < end) {
a[start++] = a[end];
}//从右边选取第一个小于tmp的值复制到a[start]
for (; start < end && a[start] < tmp; start++);
if (start < end) {
a[end--] = a[start];
}//从左边选取第一个大于tmp的值复制到a[end]
}
a[start] = tmp; //将保存在tmp里面的a[start]存到最终的位置
return start;
}

/* n为数组的个数,要找出第k大的值,k从1开始计数 */
int findk(int *a, int start, int end, int k) {
assert(k > 0 && k <= end - start + 1);
int tmp = partion(a, start, end); //随机拆分成左小右大的2部分
int nlower = tmp - start + 1; //左边小元素的个数
if (k == nlower) { //若左边小元素个数恰好为k,则返回
return a[tmp];
} else if (nlower < k) { //左边元素个数比k少,则在右边继续寻找剩下的k-nlower
return findk(a, tmp + 1, end, k - nlower);
} else {
return findk(a, start, tmp - 1, k);//继续在左边部分寻找第k大
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息