堆排序的算法是紧接希尔排序,它的原理就是把一个待排序的序列先创建成一个二叉树,这个二叉树具有的性质是:每一个节点都大于它的孩子节点,即为:大顶堆,反之即为小顶堆。
要实现这样的二叉树,我们从下往上,从左往右将每个非叶子节点作为根节点,将其和它的叶子节点作比较,实施交换,将最大的节点上升为非叶子节点。所以我们先要找到二叉树的根节点,这里可以用 n/2 来表示最后面非叶子节点的坐标。在这个循环操作之后,最大的节点上升为了整颗二叉树的根节点。也就是说在整个序列中第一个数就是最大的数,注意:最后一个数不一定是最小的数。
代码实现如下:
先创建一个结构体:
#define MAXSIZE 100
typedef struct{
int r[MAXSIZE];
int length;
}
在程序中我们是从下标为 1 来开始存储和遍历数的。
void createHeapSort(SqList *L){
int i;
for(i = L->length/2; i >0; i--){
heapAdjust(L,i,L->length);
}
}
这里我们从最后一个非叶子节点开始向上走,没走一次都将子树中最大的节点上升为非叶子节点
void heapAdjust(SqList *L, int s, int m){
int j, temp;
temp = L->r[s];
for(j = 2*s; j <= m; j *= 2){
if(j < m && L->r[j] < L->r[j+1]){
++j;
}
if(temp >= L->r[j]){
break;
}
L->r[s] = L->r[j];
s = j;
}
L->r[s] = temp;
}
这里的作用就是创建一个二叉树,将这个树中最大的节点上升为整棵树的根节点。
接下来就可以进行排序了:
void heapSort(SqList *L){
int i;
for(i = L->length; i > 1; i--){
swap(L,i,1);
heapAdjust(L,1,i-1);
}
}
这里将堆顶元素和最后的一个元素做交换,这样一来整个序列中最开始的数即使整个序列最大的值。接着就可以将最大的数排除,重新创建一个树。以此循环。就可以不断地将最大的数升上来,这里有点像冒泡。