堆排序,思想就是先建立最大堆,然后从最大堆中取出最大数,作为数组的最后一个数据,重复并把数据取完。
排序的数组结构,包含堆数组的长度,有效的堆大小 和堆数据
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)
创建最大堆,从下往上实现子堆最大堆,
前提定理:
![](https://i-blog.csdnimg.cn/blog_migrate/4b1ceace7f0dd5c0a875209b0d1832de.png)
过程:
伪代码如下
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);
}