堆
所有的完全二叉树都可以用数组来表示,但不一定都是堆,在这里堆使用一个数组来进行表示
存在数组中的完全二叉树通过孩子节点寻找父亲节点的方式
parent = (children-1)/2
大堆
树中的所有父亲节点都大于等于它的孩子节点
小堆
树中的所有父亲节点都小于等于它的孩子节点
添加节点
- 直接在尾i节点赋值
- 向上调整
删除根节点
- 将根节点与数组最后一个元素交换
- 然后向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
assert(a);
int child = parent * 2 + 1;
while (child < n)
{
if (a[child - 1] < a[child])
{
child--;
}
if (a[child] < a[parent])
{
int temp = a[child];
a[child] = a[parent];
a[parent] = temp;
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void AdjustUp(HPDataType* a, int n)
{
assert(a);
int child = n - 1;
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[child - 1] < a[child])
{
child--;
}
if (a[child] < a[parent])
{
int temp = a[child];
a[child] = a[parent];
a[parent] = temp;
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
堆排序
pop 头结点,然后将结果打印
topK 问题
N 个数字,取到前K 个最大的数
创建一个堆,大小为k ,首先向堆内push 数据,到达k 个后停, 此时这k 个数为数组前k 个数字的最大的k 个值,然后如果数据比堆的top 大,直接覆盖top ,然后向下调整
这样,堆内的数据不断更新调整,每次更新后都是已遍历的数据中最大的前k 个数, 遍历结束后,再进行一遍堆排序,打印输出得到最终结果
该算法的空间复杂度:O(K)
该算法的时间复杂度:O(N*logK)
|