下面我们来看一下堆排序算法:堆排序算法实际当中常常会用到,因为堆这个数据结构是非常普通的,计算机中经常会遇到,那么我们就有必要了解一下利用堆来排序,下面的案例就是一个堆排序算法,该算法的运行时间一般,但由于堆这个数据结构经常遇到,所以还是有用武之地的!
C语言版本的案例:
/* 欲详知本程序,请阅读《算法导论》中关于堆排序的章节 */ #include "stdio.h" #include "conio.h" #include "math.h" #define N 23 /* 堆排序算法:时间复杂度是nlg(n),以2为底,不是10! 它能够进行原址排序,堆这一数据结构有很多应用。可以 作为高效的优先队列,例如作业调度或事件驱动模拟器 这样的应用程序来说,优先队列对应着应用程序中的对象 在堆来实现优先队列时,需要在堆中的每个元素里存储对 应对象的句柄。句柄的准确含义依赖于具体的应用程序。 同样,在应用程序的对象中,我们也需要存储一个堆中对 应元素的句柄。通常这一句柄是数组的下标。由于在堆的 操作过程中,元素会改变其在数组中的位置,因此在具体 的实现中,在重新确定堆元素位置时,也需要更新相应应 用程序对象中的数组下标。因为对应用程序对象的访问细 节强烈依赖于应用程序及其实现方式,这里一言两语也很 难说的清,所以下面的例程仅给出了(最大堆)堆排序的简 单实现过程。注意待排序数组的0号元素并不能用于排序 有特殊作用,最终输出一个从小到大的有序数组 */ void heap_sort(int A[],int heap_size) { int i=0,temp; build_heap_sort(A,heap_size); for(i=N;i>1;i--) { heap_size--; temp=A[i]; A[i]=A[1]; A[1]=temp; check_heap(A,1,heap_size); } return ; } /*返回左子树节点的下标,不是值,下标代表了在堆中的 位置,有实际意义*/ int left_node(int i) { return i*2; } int right_node(int i) //返回右子树节点的下标 { return i*2+1; } /*根据堆的大小建立一个最大堆,堆的第一个元素从下标为 1处开始,不是0!*/ int build_heap_sort(int A[],int heap_size) { int i=0; for(i=(int)floor(heap_size/2.0);i>0;i--) { check_heap(A,i,heap_size); } return ; } /*进行最大堆的排序,保持最大堆的性质:根节点的值一定大于 它的左子树和右子树,如果发现子节点更大,则进行互换,互换后 被替换的子节点仍然可能违反这个性质,所以对替换后的子节点 也进行同样的操作。*/ int check_heap(int A[],int node,int heap_size) //node为下标,代表了在堆中的位置 { int largest=0,left,right,temp; left=left_node(node); right=right_node(node); if((A[left]>A[node])&&(left<=heap_size)){largest=left;} else largest=node; if((A[largest]