一,使用堆排序法之前,需要了解堆的特性:
1,堆一般都用数组的方式来存储,堆分为“最大堆”和“最小堆”;
2,以“最大堆”为例:
(1)一个节点最多有两个子节点,即左右节点,每个节点都是一个堆;
(2)父节点的值不小于子节点的值;
(3)一个i节点,其父节点为(i-1)/2,左节点(2*i+1),右节点(2*i+2)
一个最大堆例子:
数组 int a[]:
83 | 78 | 81 | 48 | 17 | 27 |
二,将一个数组形成堆(以最大堆为例)
数组a[]:
27 | 48 | 81 | 78 | 17 | 83 |
形成最大堆思路:
(1)len=6为数组长度, i=len/2=3,从第i个节点开始,将第i个节点形成最大堆,直至i<0,即到根节点;
(2)在第i个节点中,选出子节点(2*i+1)和(2*i+2)中的最大值;
(3)父节点和子节点最大值比较,如果子节点值更大,则位置互换,否则不变;
(4)重复前三个步骤
图示过程:
注:本例len=6,i=len/2=3,由于a[3]=78无子节点,所以图例从a[2]开始展示。
实现代码:
/************************************************************************************** * Description: 形成一个最大堆 * Input Args: a代表数组指针,j为要排序的数索引,num为数据长度 * Output Args: 得到一个最大堆 * Return Value: 1 *************************************************************************************/ int slipdown (int a[], int j, int num) { int temp = a[j]; int i; for(i=(2*j+1); i<=num; i=(2*j+1)) { /* 保证左右子节点存在前提,找出最大值 */ if(i+1<num && a[i]<a[i+1]) i++; /* 如果子节点更大,移到父节点 */ if(i<num && a[i]>temp) a[j]=a[i]; else break; /* 转入子节点 */ j=i; } a[j]=temp; return 0; } /* ----- End of slipdown() ----- */
三,堆排序
堆建好之后堆第0个数据是堆中最大的数据,将第0个数据和最后一个数据交换之后,再次形成最大堆,直到最后堆剩余一个数。此时,得到一个由小到大的数组。如果需要得到由大到小数组,可以形成最小堆。
实现代码:
/**************************************************************************************
* Description : 打印函数
* Input Args : a为数组指针; num为数组长度; str为传入需要指针,指向需要打印字符串
* Output Args :
* Return Value:
*************************************************************************************/
void print(int *a, int num, char *str) { int i = 0; if(num==0) return; printf("show the data %s structure:\n", str); for(i=0; i<num; i++) { printf("%3d ", *(a+i)); } printf("\n"); }/* ----- End of print() ----- */
/**************************************************************************************
* Description:
* Input Args:
* Output Args:
* Return Value:
*************************************************************************************/
int swap (int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
return 0;
} /* ----- End of swap() ----- */
/************************************************************************************** * Description: 堆排序法 * Input Args: a为数组指针, num为数组长度 * Output Args: * Return Value: *************************************************************************************/ int heap_sort (int *a, int num) { int i; if(num==0) return -1; /* make a large heap top */ for(i=num/2; i>=0; i--) slipdown(a, i, num); print(a, num, "heap"); /* The heap sort */ for(i=num-1; i>=1; i--) { swap(&a[i], &a[0]); slipdown(a, 0, i); } return 0; } /* ----- End of heap_sort() ----- */
参考链接:
维基百科排序算法大全:http://zh.wikipedia.org/wiki/排序算法
白话经典算法系列之七 堆与堆排序:http://blog.csdn.net/morewindows/article/details/6709644/