堆排序:
基本思想:
以升序为例,
当我们要实现一个堆排序的时候,首先考虑是建大堆还是小堆,如果建小堆,根节点一定是最小的,而根节点的子节点不一定是次小的(如下图一)。因此我们每次都需要重新对堆进行全部的调整,保证根节点是已有元素中最小的一个。但是当我们使用大堆是,根节点一定是最大的,根节点的子节点一定是次大的,因此每次只需调节根节点即可,效率较高。
*总之:实现升序,建立大堆,实现降序,建立小堆
代码实现:
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void ADjustDown(int* a, int n, int root)
{
int parent = root;
int child = parent * 2 + 1;
while (child<n)
{
if (child+1<n&&a[child + 1] > a[child])
child += 1;//选出值大的孩子
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* a, int n)
{
//建大堆
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
ADjustDown(a, n, i);
}
int end = n - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
ADjustDown(a, end, 0);
--end;
}
}
TopK:
解决的问题:从大量的数据中找出最大的或者最小的K个数据(K值一般较小)
找最大的,用小堆
找最小的,用大堆
代码的简单实现
//找最大的k个
void TopK(int* a,int length,int k)
{
Heap hp;
HeapCreate(&hp,a, k);
for (int i = k; i < length; ++i)
{
if (a[i]>Heaptop(&hp))
{
HeapPop(&hp);
HeapPush(&hp, a[i]);//插入的时候,会进行调堆,使堆始终为小堆
}
}
HeapPrintf(&hp);
}