引言:
一个堆的首元素往往是最大值或者最小值,因此我们可以利用这一特性实现对一组数进行排序。
须注意的是:大堆可以实现一组数的升序排列,小堆则用来实现一组数的降序排列。
实现思路:
当我们有一个堆后(这里用小堆为例):
我们可将首元素(这里即最小的元素)与最后一个元素交换并让堆的大小减一。(因为我们这里已经把堆中最小的数放在了最后的位置,我们剩下要做的便是对其余的元素排序)。
因为父节点的两棵子树任然为小堆,因此对根节点进行向下调整(用向下调整算法),得到一个小堆,第二小的元素便又到了堆顶。
往复上面的操作,我们便对一组数进行了降序排列。
代码实现
向下调整算法:(时间复杂度 :log N)
前提:根节点(这里指函数传参接收的节点)的两棵子树都为小堆(或大堆)
功能:将根节点变为堆顶(即根节点值为最大值或者最小值)
//用于交换子节点和父节点的值
void Swap(int* a, int*b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//向下调整算法
void AdjustDown(int* array, int numsSize, int root)
{
int father = root ;
int child = father * 2 + 1;
while (child < numsSize)
{
//建小堆
if (child + 1 < numsSize && array[child +1] < array[child ])
{
child = child + 1;
}
//迭代,让父节点和子节点往树的下层走
if (array[child] < array[father])
{
Swap(&array[child] , &array[father]);
father = child;
child = father * 2 + 1;
}
else
{
//说明堆已经构建好了
break;
}
}
}
堆排序:先构造一个堆,再对该堆进行排序
//堆排序---升序建大堆,降序建小堆
void HeapSort(int* array, int numsSize)
{
int i = numsSize - 1;
//构造一个堆
for ( i; i >= 0; i--)
{
AdjustDown(array ,numsSize ,i);
}
int total = numsSize - 1;
for (total; total > 0; --total )
{
Swap(&array[0], &array[total]) ; //将首元素(这里即最小的元素)与最后一个元素交换
//并让堆的大小减一。因为父节点的两棵子树任然为小堆,因此
//对根节点向下调整,得到一个小堆,第二小的元素又到了堆顶
AdjustDown(array, total, 0);
}
}
至此整篇博客已分享完,因编者水平有限,若文章有错误或讲的不清楚的地方,恳请各位大佬评论区留言指正。