堆排序
二叉树的性质是堆排序的关键点。
二叉树的性质5,如果一颗有n个结点的完全二叉树的结点按层序编号(从第一层到最后一层,每层从左往右),则对任一结点i(1<=i<=n)有:
(1) 如果i=1,则结点i是二叉树的根节点;如果i>1,则其双亲是结点i/2(取整数部分)。
(2) 如果2i>n,则结点i无左孩子;否则其左孩子是结点2i。
(3) 如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1。
利用二叉树的性质,将待排序的数组进行大堆处理(小堆处理)。大堆即将二叉树的最大值顶到根节点,小堆即将二叉树的最小值顶到根节点。在将根节点的值与二叉树最后的一个结点互换,除去最后一个结点外的所有结点再重复上述过程。
算法实现一:数组的下标从0开始,而二叉树的下标从1开始。其他的参见上面说明。
void HeapSort(int *num, int length)
{
int i;
for(i=length/2;i>0;i--)
HeapAdjust(num,i,length);
for(i=length;i>1;i--)
{
wap(&num[0],&num[i-1]);
HeapAdjust(num,1,i-1);
}
}
void HeapAdjust(int *num, int s, int length)
{
int i,j;
int tmp = num[s-1];
for(j=2*s;j<=length;j*=2)
{
if(j<length && num[j-1]<num[j])
j++;
if(tmp >= num[j-1])
break;
num[s-1] = num[j-1];
s = j;
}
num[s-1] = tmp;
}
执行结果:
6 3 8 5 71 0 4 2 最初数组元素
6 3 8 5 71 0 4 2
6 3 8 5 71 0 4 2
6 7 8 5 31 0 4 2
8 7 6 5 31 0 4 2 构建大堆结束
8 7 6 5 31 0 4 2
2 7 6 5 31 0 4 8 首尾元素互换
7 5 6 4 31 0 2 8
7 5 6 4 31 0 2 8
2 5 6 4 31 0 7 8
6 5 2 4 31 0 7 8
6 5 2 4 31 0 7 8
0 5 2 4 31 6 7 8
5 4 2 0 31 6 7 8
5 4 2 0 31 6 7 8
1 4 2 0 35 6 7 8
4 3 2 0 15 6 7 8
4 3 2 0 15 6 7 8
1 3 2 0 45 6 7 8
3 1 2 0 45 6 7 8
3 1 2 0 45 6 7 8
0 1 2 3 45 6 7 8
2 1 0 3 45 6 7 8
2 1 0 3 45 6 7 8
0 1 2 3 45 6 7 8
1 0 2 3 45 6 7 8
1 0 2 3 45 6 7 8
0 1 2 3 45 6 7 8
0 1 2 3 45 6 7 8