原理:
将无序序列看成一个完全二叉树,根结点即list[0]。将二叉树构造成最大(最小堆),然后将首元素(即最大(最小)元素)与无序序列的末尾元素交换,将剩下的无序序列调整为最大(最小)堆,交换首元素与末尾元素,依次类推,直至无序序列元素剩余一个元素。
对排序的一般实现:
void swap(int *a,int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void heapify(int list[],int root,int n)
{
/* list subscripts start from 0. */
int child;
int temp;
temp = list[root];
child = 2 * root + 1;
while(child<=n)
{
if(child<n && list[child]<list[child+1])
child++;
if(temp>list[child])
break;
else
{
list[(child-1)/2] = list[child];
child = 2 * child + 1;
}
}
list[(child-1)/2] = temp;
}
void heapSort(int list[],int n)
{
/* n the the max subscript of elements in list. */
int i,j;
for(i=(n-1)/2;i>=0;i--)
heapify(list,i,n);
for(j=n-1;j>=0;j--)
{
swap(&list[j+1],&list[0]);
heapify(list,0,j);
}
}
测试数据如下显示:
76 59 67 85 16 54 47 50 68 37
85 76 67 68 37 54 47 50 59 16
76 68 67 59 37 54 47 50 16 85
68 59 67 50 37 54 47 16 76 85
67 59 54 50 37 16 47 68 76 85
59 50 54 47 37 16 67 68 76 85
54 50 16 47 37 59 67 68 76 85
50 47 16 37 54 59 67 68 76 85
47 37 16 50 54 59 67 68 76 85
37 16 47 50 54 59 67 68 76 85
16 37 47 50 54 59 67 68 76 85
由于无序序列的首元素下标为0,对于任意结点i,其左右儿子结点的下标为2*i+1和2*i+2,对于任意结点child,其父结点的下标为(child-1)/2(正如上述代码实现)。若首元素的下标从1开始,那么对于任意结点i,其左右儿子结点下标为2*i和2*i+1,对于任意结点child,其父结点的下标为child/2。