堆排序(heap sort)是J.Willionms在1964年提出的一种选择类排序方法,是在简单选择排序方法的基础上借助与完全二叉树的结构而形成的一种排序方法,是完全二叉树顺序存储结构的应用。
堆排序的基本思想:根据原始记录的关键字序列建立初始堆,使得堆顶元素是关键字最大(最小)的记录,然后删除堆顶元素并将其保存到数组中。继续调整剩余的关键字序列使之重新构成一个新堆,再删除关键字次大(次小)的记录并将其保存到数组中;如此反复,直到堆中只有一个记录为止。此时,数组中所有元素是一个按关键大小顺序进行排列的有序序列。
堆排序的C语言实现如下:
/*************************************************************
函数名称:static void sift(int a[], int k, int n)
参 数:int a[]---待排序的数据
int k-----待调整点的下标(待调整为堆的节点)
int n-----数组a中元素个数
功 能:对以a[k]为根节点的完全二叉树进行大根堆筛选算法,
完成一次筛选
返 回 值:无
说 明:static关键字指明了该函数只能在本文件中使用
**************************************************************/
static void sift(int a[], int k, int n)
{
int temp, i, j;
i = k; // i表示调整点的位置,即父节点下标
j = 2*i+1; // a[j]为父节点a[i]的左孩子
temp = a[i]; // 保存父节点
while(j<n)
{
if(j+1<n && a[j]<a[j+1])
j++; // j为i的孩子节点中关键字较大的记录的下标
if(temp<a[j]) // 如果孩子节点的关键字大于父结点
{
a[i] = a[j]; // 将a[j]调整到父结点位置
i = j; // 更新父结点下标
j = 2*i+1; // 更新父结点的左孩子结点下标
}
else // 如果孩子节点的关键字小于或等于父结点,则筛选结束
break;
}
a[i] = temp; // 被筛选节点的值放入正确的位置,完成建堆的一次筛选
}
/*************************************************************
函数名称:void HeapSort(int a[], int n)
参 数:int a[]---待排序的数据
int n-----数组a中元素个数
功 能:对待排序数据进行堆排序
返 回 值:无
说 明:无
**************************************************************/
void HeapSort(int a[], int n)
{
int tp, i;
// 根据初始关键字,建立初始堆
for(i=n/2; i>=0; i--)
sift(a, i, n);
// 进行n-1趟筛选,调整,完成堆排序
for(i=n-1; i>0; i--)
{
// 将堆顶元素a[0]与最后一个元素交换位置,将最大(最小)数据移动到最后
tp = a[i];
a[i] = a[0];
a[0] = tp;
// 将去掉堆顶元素后的序列,重新调整为一个新堆
sift(a, 0, i);
}
}