重温算法导论(六) 堆排序

堆排序,思想就是先建立最大堆,然后从最大堆中取出最大数,作为数组的最后一个数据,重复并把数据取完。

排序的数组结构,包含堆数组的长度,有效的堆大小 和堆数据

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);
}


猜你喜欢

转载自blog.csdn.net/hahackeris/article/details/80925523