首先我要说明一点,在看了很多网上的资料的前提下,我一开始以为堆就是完全二叉树。其实这个概念是错的。其次,堆排序也不是只能针对完全二叉树,只是完全二叉树更为方便实现。
堆排序原理与图解可以详见
https://www.cnblogs.com/chengxiao/p/6129630.html
这篇博客介绍的非常好,在这里我就不多说了。
以下是本人的代码与注释
#include <stdio.h>
//堆排序
void AdjustMinHeap(int *a, int pos, int len)
{
int temp;
int child;
temp = a[pos];//temp 暂存要比较的父结点的值
while(2 * pos + 1 <= len)//2 * pos + 1 <= len 确保以pos为结点坐标的结点是父结点不是叶子结点
{
child = 2 * pos + 1;
if (child < len && a[child] > a[child + 1])//a[child]>a[child+1]比较左孩子结点和右孩子结点值的大小,这里是小顶堆,如果右结点小于左结点,child坐标+1;child<len确保父结点有两个孩子结点
{
child++;
}
if (a[child] < temp)//把孩子结点中较小的值和父结点比较,这里是小顶堆,如果孩子结点中较小的值小于父结点的值,则交换父结点和较小孩子结点的值
{
a[pos] = a[child];
a[child] = temp;
}
else//这里是小顶堆,如果两个孩子结点的值都大于父结点,则退出循环
{
break;
}
pos = child;//pos = child 为了交换父结点和较小的孩子结点的坐标
}
}
void Swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void PrintArray(int *a, int length)
{
int i;
for (i = 0; i < length; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
void HeapSort(int *array, int len)
{
int i;
for (i = len / 2 - 1; i >= 0; i--) //初始化堆的形成(这里是小顶堆)
{
AdjustMinHeap(array, i, len - 1);
}
for (i = len - 1; i >= 0; i--)
{
Swap(&array[0], &array[i]);//利用小顶堆的性质,根节点是当前树的最小值与数组内的尾元素交换
AdjustMinHeap(array, 0, i - 1);//重新形成小顶堆
}
}
int main()
{
int array[] = { 3, 1, 13, 14, 27, 18 };
/*
0
13 1
14 27 18
*/
int length = sizeof(array) / sizeof(array[0]);
HeapSort(array, length);
PrintArray(array, length);
return 0;
}