找最小的 k 个数据
需要建大堆,TopK 最好不要在原数组上调整
- 向下调整
void ArrayAdjustDown(int array[], int size, int root)
{
int parent = root;
while (1) {
// 先判断有没有孩子(叶子结点)
// 数组角度去想 -> 孩子的下标是否越界
// 只要判断左孩子的下标(因为是完全二叉树)
int left = parent * 2 + 1;
if (left >= size) {
// 越界,没有左孩子,也肯定没有右孩子
return;
}
// 一定有左孩子
int maxChild = left;
if (2 * parent + 2 < size && array[2 * parent + 2] > array[left]) {
// 前一个条件是判断右孩子有没有
// 后一个条件判读是右孩子是否比左孩子大
maxChild = 2 * parent + 2;
}
if (array[parent] > array[maxChild]) {
return;
}
// 交换 root 和 maxChild 下标所在的值
int t = array[parent];
array[parent] = array[maxChild];
array[maxChild] = t;
parent = maxChild;
}
}
int * TopK(int array[], int size, int k)
{
int *heapArray = (int *)malloc(k * sizeof(int));
assert(heapArray);
// 搬 前 k 个数过去
for (int i = 0; i < k; i++) {
heapArray[i] = array[i];
}
// 建堆,建大堆
// 这里的 size 其实是 k
for (int j = (k - 2) / 2; j >= 0; j--) {
ArrayAdjustDown(heapArray, k, j);
}
for (int m = k; m < size; m++) {
if (array[m] >= heapArray[0]) {
continue;
}
heapArray[0] = array[m];
ArrayAdjustDown(heapArray, k, 0);
}
return heapArray;
}
void TestTopK()
{
int array[] = { 1, 4, 9, 4, 2, 7, 8, 5, 3, 6, 2, 2, 3 };
int size = sizeof(array) / sizeof(int);
//求最小的5个数
int *r = TopK(array, size, 5);
}
- 结果