堆排序依赖于上午写道的构建堆和调整堆。
基本思想:
(1)首先执行BuildHeap(以最大堆为例),则arr[0]已经是最大元素了,如果我们要按照从小到大排序,那么它应该被放在arr[n-1]上,于是,我们swap arr[0]和arr[n-1]。
(2)类似的,我们让i从n-1到0,依次执行调整堆,AdjustHeap(i,n),每次调整完成后,堆顶部一定是最大元素,正好把他换到i-2上。
上述的思路和选择排序是不是非常相似!
改进:
调整堆实际用到了递归方法,而其实它是可以非递归化的。非递归化后,性能较递归版本有略微的提升。
全部代码如下:
#include <stdio.h>
typedef long TYPE;
void swap(TYPE* a, TYPE* b)
{
TYPE tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
//adjust heap()
void heapify(TYPE* heap, int idx, int n)
{
//left and right index
int left = 2 * idx + 1;
int right = 2 * idx + 2;
int large = 0;
//Check left
if(left<n && heap[left]>heap[idx])
{
large = left;
}
else
{
large = idx;
}
//Check right
if(right<n && heap[right]>heap[large])
{
large = right;
}
//Swap idx and max one
if(idx!=large)
{
swap(&heap[idx], &heap[large]);
heapify(heap, large, n);
}
}
void buildHeap(TYPE* heap, int n)
{
int i=n/2-1;
for(; i>=0; i--)
{
heapify(heap, i, n);
}
}
void heapSort(TYPE*heap, int n)
{
int i;
buildHeap(heap, n);
for(i=n-1; i>=1; i--)
{
swap(&heap[0], &heap[i]);
heapify(heap, 0, i);
}
}
int main()
{
TYPE arr[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int i;
int len;
len = sizeof(arr)/sizeof(TYPE);
//Test heapify
//heapify(arr, (len-1)/2, len);
//buildHeap(arr, len);
heapSort(arr, len);
//print
for(i=0; i<len; i++)
{
printf("%ld ", arr[i]);
}
printf("\n");
}