堆排序是简单选择排序的改进,是一种不稳定的排序方法。
基本思路:对一组待排序的记录序列,先将其关键字按堆的定义排列一个序列(称为初建堆),找到最小(最大)关键字后,将其取出。用剩余的n-1个元素再重建堆,便可得到次小(次大)值。如此反复执行,直到全部关键字排好序为止。
#include<stdio.h>
#define Type int
#define MARK 0 //占据a[0],不起实际作用
#define NUM 6
#define Num NUM - 1 //实际要排序的数
void print(Type A[])
{
int i;
for(i = 1; i< NUM; i++)
printf("%d ", A[i]);
printf("\n");
}
void adjust(Type *buf, int t,int w)
{
int i,j;
Type x;
i = t;
x = buf[i]; //待筛选的值存放在辅助单元中
j = 2*i ; //buf[j] 是buf[i]的左孩子
while(j<=w) //确定不越界
{
if((j < w)&&(buf[j] > buf[j + 1])) //若存在右子树且右子树的关键值小,则从右分支筛选,
j++; //否则从左子树筛选
if(x > buf[j]) //若待筛选的值大于子树的值
{
buf[i] = buf[j]; //进行对调
i = j;
j = 2*j; //继续搜索
}
else
{
break; //根不大于他的孩子的值,调整完毕,退出循环
}
}
buf[i] = x; //将待排序的值放入恰当的位置
}
void heap_sort(Type *buf, int n)
{
int i;
Type x;
for(i = n/2;i >= 0; i--) //初建堆
adjust(buf, i, n);
//初始化堆的输出
printf("初始化堆的输出:");
print(buf);
for(i = n; i > 1; i--) //进行n-1趟排序
{
x = buf[1]; //将第一个记录和当前堆中最后一个记录互换
buf[1] = buf[i];
buf[i] = x;
adjust(buf,1,i-1); //已经筛选buf[1]结点,得到具有n-1个结点的堆。
//重建堆的输出
printf("第%2d次重建堆的输出:",(NUM - i));
print(buf);
}
}
int main()
{
Type num[NUM] = {MARK,1,32,2,12,23};
printf("Original array:");
print(num);
heap_sort(num,Num); //Num = NUM - 1
printf("Sorted array:");
print(num);
return 0;
}