一、提出问题
假设现在有N个数,我们需要选出N个数中前 K 个较大的数
二、思路分析
1、先从N个数中取出K个数,构成一个数组arr
2、将数组arr构建成一个小堆(堆顶是最小的数)
3、然后从剩下的 N-K 个数中逐个取出 数,和堆顶的数比较
-如果比堆顶的数更大,则替换堆顶的数,然后向下调整(最小的数被删除了,选出次小的数)
-如果比堆顶的数更小,则保持不变
4、重复第三步,直到剩下的 N-K个数都参与了比较
整体思路就是 如果比堆顶的数更大,则替换堆顶的数,那么最小的数会被删除
否则不替换,如此往复,最小的数会被替代,仅剩下较大的数
三、代码实现
建小堆在可以参考如下
void SelectTopK(int* a, int val,const int size)
{
//建小堆,可沿用链接中博客的代码
CreateHeap(a, size);
//和堆顶的元素比较
a[0] = a[0]<val?val:a[0];
//由于原本就是小堆,直接从根部向下调整
AdjustDown(a, 0, size);
for (size_t i = 0; i < size; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
四、测试
int main()
{
int arr[] = { 12,45,53,64,75,78,96,34};
for (size_t i = 0; i < 10; i++)
{
//通过随机值来表示剩下的N-K个数
SelectTopK(arr, rand() % 100, sizeof(arr) / sizeof(arr[0]));
}
return 0;
}
测试结果: