建堆有两种方法:向上调整,向下调整。
向上调整:
顾名思义,是将孩子和母亲进行交换,堆的实现使用数组实现的,所以母子的下标是有迹可循的,
可知左孩子=母亲*2+1
右孩子=母亲*2+2
对于大堆和小堆孩子和母亲交换的条件也不同:
大堆:如果孩子>母亲,就进行交换,其他情况不换
小堆:如果孩子<母亲,就进行交换,其他情况不换
迭代条件:child = parent parent = (child-1)/2
代码如下:
void AdjustUp(HPDataType* a, int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
此代码是建大堆的代码,建小堆只需要将 a[child] > a[parent] 改为a[child] < a[parent]。
向下调整:
同样,是将母亲和孩子交换,可知左孩子=母亲*2+1,右孩子=母亲*2+2,一个母亲对应的是两个
孩子,所以要先进行比较孩子的大小:
大堆:取较大的孩子
小堆:取较小的孩子
对于大堆和小堆孩子和母亲交换的条件也不同:
大堆:如果较大的孩子>母亲,就进行交换,其他情况不换
小堆:如果较小的孩子<母亲,就进行交换,其他情况不换
代码如下:
void AdjustDown(HPDataType* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
//选出孩子中较大的
if (child + 1 < n && a[child] < a[child + 1])
{
child += 1;
}
//向下调整
if (a[parent] <= a[child])
{
Swap(&a[parent], &a[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
此代码是建大堆的代码,如果要建小堆,则需更改两个条件:
条件一:a[child] < a[child + 1]改为a[child] > a[child + 1]
条件二:a[parent] <= a[child]改为a[parent] >= a[child]