什么是堆排序呢?
堆排序就是把一组数据用一个完全二叉树表示,从总结点数/2的结点开始,与它的左右子树进行比较,把大的数据(或者小的数据)放在子树,小的数据放在根的位置,比较到整棵树的根节点,将根节点的数据弹出去,一直到每个结点都弹出去之后,顺序也就排好了。
拿例子来看吧
比如一组数据:
16 12 35 85 96 74 58 96 12 20
图片表示
存入完全二叉树
一共有n = 10个结点,那么从n=5开始比较,也就是从结点95开始
95 > 20,所以95与20交换位置
n = 4
85 > 12
n = 3
35<74,35<58,所以不需要进行移动
n = 2
12=12,12<20,不需要进行移动
n = 1
16 > 12
输出12,12与95对换位置
目前结点数为9
n = 4
12<95,12<85,不需要交换
n = 3,35 < 74,35 < 58,不需要交换
n = 2
16>12
n = 1,95>12,95>16,95>85
输出12
开始新一轮,直到所有数据都输出
… …
动画效果
代码
//堆排序
/*筛选算法*/
void pileAdjust(OrderList* L, int s, int length)
{
RecordType key;
int j;
key = L->R[s];
for (j = 2 * s; j <= length; j=j*2)
{
if (j < length && L->R[j].key < L->R[j + 1].key) //j < length 保证了右子树一定存在
{
j++;
}
if (key.key < L->R[j].key) //如果比比较的数小,就换位置
{
L->R[s] = L->R[j];
s = j;
}
}/*for j*/
L->R[s] = key;
}
/*堆排序算法*/
void pileSort(OrderList* L)
{
RecordType tmp;
int i;
/*进行第一次堆排序,建成小根堆*/
for (i = L->length / 2; i > 0; i--)
{
pileAdjust(L, i, L->length);
}/*for i */
/*将根节点与尾部的结点换位置之后,再进行筛选*/
for (i = L->length; i > 0; i--)
{
tmp = L->R[i];
L->R[i] = L->R[1];
L->R[1] = tmp;
pileAdjust(L,1,i-1);
}
}