根据算法导论第二版中文版第六章堆排序内容所写的代码(p73),采用c语言,编译器为vc2008
程序的说明:
/*****************
1. 定义数组的长度 ArrayLength = 10
2. 堆排序的思路:
建堆,使一个二叉树中的数据符合堆的定义,即是根的数值大于左右子结点的值,该功能由buildMaxHeap()函数完成
当堆的根结点的值发生变化时能够重新建立一个堆,该功能由maxHeapify()函数完成
有了上述两个函数后,首先建堆,根结点便是最大值,将之交换到最后,之后排除掉最后一个结点,
不断对剩余结点的maxHeapify,便可以在根结点得到第二大的值、第三大的值、。。。直到最后一个为最小值
由此完成堆排序
3. 程序其他函数说明:
创建一个数组,该数组构成一个二叉树,可以对该数组建堆。creatArray();
回收创建数组时申请的空间 destroyArray();
打印数组中的各个值 printArray();
得到左右子树结点的的位置leftChild(),rightChild();
交换指针所指的两个值 exchange();
得到两数中的最大值max()
得到三个数种的最大值maxThreeNum();
*****************/
#include <stdio.h> #define ArrayLength (10) int leftChild(int i); int rightChild(int i); void maxHeapify(int* a, int start, int end); void buildMaxHeap(int* a, int arrayLength); void heapSort(int* a,int arrayLength); int test(int* a, int arrayLength); int* creatArray(int arrayLength); void destroyArray(int* a); void printArray(int* a, int arrayLength); void exchange(int* num01, int* num02); int max(int num01, int num02); int min(int num01, int num02); int maxThreeNums(int num01, int num02, int num03); void exchange(int* num01, int* num02); int main(int argc, char** argv){ int* a; a = NULL; a = creatArray(ArrayLength); printArray(a,ArrayLength); heapSort(a,ArrayLength); printArray(a,ArrayLength); destroyArray(a); return 0; } int test(int* a, int arrayLength){ int i; //编程测试代码 return 0; } //得到左右子结点在数组中的位置,用位运算可以更快速得到结果,使用乘号容易理解。 int leftChild(int i){ int position; position = 2*i; return position; } int rightChild(int i){ int position; position = 2*i+1; return position; } int* creatArray(int arrayLength){ int i; int* a; //数组第一个元素a[0]不用,从a[1]开始,所以多申请了一个int的空间 a = (int*)malloc((arrayLength+1)*sizeof(int)); for(i=1;i<=arrayLength;i++){ *(a+i) = arrayLength-i; } return a; } void destroyArray(int* a){ free(a); } void printArray(int* a, int arrayLength){ int i; i = 0; printf("==============================\n"); printf(" array content \n"); printf("==============================\n"); for(i=1;i<=arrayLength;i++){ printf("a[%d] = %d",i,*(a+i)); printf("\n"); } } //堆排序的主要函数,maxHeapify的前提是二叉树的数组已经是一个最大堆 void maxHeapify(int* a, int start, int end){ int m; int leftChildPosition; int rightChildPosition; //首先处理越界的情况:如果是叶子结点便退出,如果左右子结点超出数组的范围也退出 if(start >= end) return ; leftChildPosition = leftChild(start); if(leftChildPosition > end)return; else if(leftChildPosition == end && *(a+start) < *(a+leftChildPosition)){ exchange(a+start,a+leftChildPosition); return; } rightChildPosition = rightChild(start); if(rightChildPosition > end)return; //其次处理普通情况:如果根结点比左右子结点的值都大,则退出 //如果左结点的值最大,交换根与左结点的值,递归处理左子树 //如果右结点的值最大,交换根与结右点的值,递归处理右子树 m = maxThreeNums(*(a+start),*(a+leftChildPosition),*(a+rightChildPosition)); if(m == *(a+start)) return; else if(m == *(a+leftChildPosition)){ exchange(a+start,a+leftChildPosition); maxHeapify(a,leftChildPosition,end); } else if(m == *(a+rightChildPosition)){ exchange(a+start,a+rightChildPosition); maxHeapify(a,rightChildPosition,end); } } //建堆,从最后面的叶子结点开始逐步往上建立 void buildMaxHeap(int* a, int arrayLength){ int i; for(i=arrayLength;i>0;i--){ maxHeapify(a,i,arrayLength); } } void heapSort(int* a,int arrayLength){ int i; int e; e = arrayLength; buildMaxHeap(a,arrayLength); for(i=arrayLength;i>1;i--){ exchange(a+1,a+i); maxHeapify(a,1,i-1); } } void exchange(int* num01, int* num02){ int tmp; tmp = *num01; *num01 = *num02; *num02 = tmp; } int max(int num01, int num02){ int tmp = num01>num02?num01:num02; return tmp; } int min(int num01, int num02){ int tmp = num01<num02?num01:num02; return tmp; } int maxThreeNums(int num01, int num02, int num03){ if(num03>max(num01,num02)) return num03; else return max(num01,num02); }