堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。定义来自百度百科。
堆排序,如果仅仅是通过PPT演示或者观看图片,看起来虽然很容易理解堆排序的思想,但是因为是树形演示,总有一种实现起来很麻烦的感觉,但其实不然,通过数组的形式来实现的话,思路也还是很容易理解的,而且代码看也不难实现。
堆分为大顶堆和小顶堆。
(1) 小顶堆 ki<=k(2i)且 ki<=k(2i+1)(1≤i≤ n)
(2)大顶堆 ki>=k(2i)且 ki>=k(2i+1)(1≤i≤ n)
例子:
1 2 3 4 5 6 7 8
小顶堆 { 4 8 7 9 10 12 11 13}
大顶堆 { 13 11 12 9 10 8 7 6}
不是堆 { 12 11 13 9 10 8 7 6}
对于一组无序的数组,如果要进行堆排序,首先应该先将这个数组变成一个堆,
如果是要对数组进行递增排序,要建大顶堆
如果是要对数组进行递减排序,要建小顶堆
建堆完成之后,要进行排序,排序的方法是用首元素与还未排好序的最后一个元素交换位置,然后进行排序。
大顶堆 { 13 11 12 9 10 8 7 6}
第一次:将 6 和 13 交换位置得到:6 ,11,12, 9, 10, 8, 7 , 13
6 比 11 ,12小,交换6 ,11得到 : 11 ,6 , 12 , 9, 10 , 8, 7
6 比 9 , 10小, 交换6,9 得到: 11 ,9 , 12 , 6 ,10 , 8 ,7
接下去同理。
结合代码起来理解会比较方便。
#include<stdio.h>
//两数交换
void swap( int * a, int *b)
{
int temp =*a;
*a= *b;
*b=temp;
}
void HeapPass( int arr[], int start , int length)
{
int j=2*start;
//不用arr[0]的原因是这里的 j , 如果j=0 , 那么 j=2*j ; j 是不会有变化的
while( j<length )
{
//因为我们数组的第一个数不用,所以j+1并不会超过数组
//这里建立的是大顶堆,可以用来做递增排序,将两个if的“<”换成“>”建立小顶堆,最后排序是递减的
if(arr[j] < arr[j+1])
j++;
//这里为什么可以用break呢?是因为我们在建堆的时候是从后面排上来的,
//所以后面的是已经排好的,即符合大顶堆的要求
if(arr[j] < arr[start])
break;
else
{
swap( &arr[j] , &arr[start]);
}
start=j;
j=j*start;
}
}
void HeapSort( int arr[] ,int length)
{
//建堆
int i;
//为什么要从i=length/2开始呢? 为什么不是从 i=1开始呢?这个问题留给大家思考。
for(i=length/2; i>0; i--)
{
HeapPass( arr, i , length);
}
for( i=1; i <length ; i++ )
{
swap( &arr[1], &arr[length+1-i] );
//将第一个数与排序好的前一个数进行交换,交换后进行堆选择
HeapPass( arr, 1 , length-i);
}
}
int main()
{
//arr[0] 不参与排序,这样实现起来比较方便
//实现过程会说明原因
int arr[11]={0,3,5,4,6,9,10,8,7,1,2};
HeapSort(arr, 10);
int i;
for( i=1; i<=10; i++)
printf("%d ",arr[i]);
getchar();
return 0;
}
/*排序结果1 2 3 4 5 6 7 8 9 10*/