堆的向下调整算法(建小堆)
向下调整算法-前提:当前树的左右子树必须都是一个小堆
向下调整算法的核心思想:选出左右孩子中小的哪一个,跟父亲交换,小的往上浮,大的往下沉建大堆则相反
如下图所示为一个向下调整法调小堆
堆向下调整算法(建小堆)
void AdjustDown(int* a, int n, int root)
{
int parent = root;
int child = parent * 2 + 1;
//孩子超过数组下标结束
while (child < n)
{
//child始终左右孩子中小的那个
if (a[child + 1] < a[child] && child + 1 <n)//防止没有右孩子
{
++child;
}
//小的往上浮,大的往下浮
if (a[child] < a[parent])
{
int tem = a[parent];
a[parent] = a[child];
a[child] = tem;
parent = child;
child = parent * 2 + 1;
}
//中途child>parent则已满足小堆,直接break
else
{
break;
}
}
}
堆的向上调整算法(建小堆)
图示:
代码实现
void AdjustUp(HPDataType* a, int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[child] < a[parent])
{
int tem = a[parent];
a[parent] = a[child];
a[child] = tem;
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
数组建堆算法(建小堆)
若左右子树不是小堆时要把左右子树处理成小堆再进行堆排序
从倒数第一个非叶子节点的位置开始向下调整
如下图所示可以按图中的步骤依次向下调整,最后一个非叶子节点的下标为 (n-1-1)/2
int n = sizeof(a) / sizeof(int);
//数组建堆算法
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(arr, n, i);
}
堆排序(降序)的实现
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)
{
int tem = a[end];
a[end] = a[0];
a[0] = tem;
//选出次小的数
AdjustDown(a, end, 0);
--end;
}
}