堆排序,思想就是先建立最大堆,然后从最大堆中取出最大数,作为数组的最后一个数据,重复并把数据取完。
排序的数组结构,包含堆数组的长度,有效的堆大小 和堆数据
A{ length heap-size A[] }
每个节点对应的父节点,左子节点,右子节点
维护最大堆的性质,先假定先假定Left[i] 和Right[i] 为最大堆,MaxHeapify(A,2)过程
实现伪代码:
MaxHeapify(A, i) //先假定Left[i] 和Right[i] 为最大堆 l = Left(i) r = Right(i) if l <= A.heap-size and A[i] < A[l] largest = l else largest = i if r <= A.heap-size and A[r] > A[largest] largest = r if largest != i exchange A[i] <=> A[largest] MaxHeapify(A, largest)
创建最大堆,从下往上实现子堆最大堆,
前提定理:
过程:
伪代码如下
BuileMaxHeap(A) A.heap-size = A.length for i = (A.length /2) downto 1 MaxHeapify(A, i)
堆排序,从最后一个数据与第一个数据交换,并减少堆的有效大小,过程如下
伪代码如下:
HeapSort(A) 堆排序 BuileMaxHeap(A) for i = A.length downto 2 exchange A[1] , A[i] A.heap-size = A.heap-size -1 MaxHeapify(A, 1)
以下为C++实现代码:
//堆排序 template<class T> struct StuA { int iLenth; int iHeapSize; T *A; }; inline int Parent(int i){ return (i+1)/2-1; } inline int Left(int i) { return 2*i + 1; } inline int Right(int i) { return 2*i +2; } //假定LEFT 和right 子树都是最大堆 template<class T> void MaxHeapify(StuA<T> stu, int i) { int l = Left(i), r = Right(i), ilargest; if(l < stu.iHeapSize && stu.A[i] < stu.A[l]) ilargest = l; else ilargest = i; if(r < stu.iHeapSize && stu.A[r] > stu.A[ilargest]) ilargest = r; if (i != ilargest){ ExchangeT(stu.A[i], stu.A[ilargest]); MaxHeapify(stu, ilargest); } } template<class T> void BuildMaxHeap(StuA<T> stu) { for(int i = stu.iHeapSize / 2 -1; i>=0; i--) { MaxHeapify(stu, i); } } template<class T> void HeapSort(StuA<T> stu) { BuildMaxHeap(stu); for (int i = stu.iLenth -1 ; i> 0; i--) { ExchangeT(stu.A[i], stu.A[0]); stu.iHeapSize = stu.iHeapSize -1 ; MaxHeapify(stu, 0); } }
int main(int argc, char* argv[]) { // int iData[10] = {16, 4, 10, 14, 7, 9, 3, 2,8,1}; int iData[10] = {4,1,3,2,16,9,10,14,8,7}; StuA<int> objA; objA.A = iData; objA.iHeapSize = objA.iLenth = 10; //BuildMaxHeap(objA); HeapSort(objA); }