堆排序
Maintaining the heap property
MAX-HEAPIFY is an important subroutine for manipulating max-heaps. Its inputs are an array A and an index i into the array. When MAX-HEAPIFY is called, it is assumed that the binary trees rooted at LEFT(i) and RIGHT(i) are max-heaps, but that A[i] may be smaller than its children, thus violating the max-heap property. The function of MAX-HEAPIFY is to let the value at A[i] "float down" in the max-heap so that the subtree rooted at index i becomes a max-heap.
MAX-HEAPIFY(A, i)
1 l ← LEFT(i)
2 r ← RIGHT(i)
3 if l ≤ heap-size[A] and A[l] > A[i]
4 then largest ← l
5 else largest ← i
6 if r ≤ heap-size[A] and A[r] > A[largest]
7 then largest ← r
8 if largest ≠ i
9 then exchange A[i] ↔ A[largest]
10 MAX-HEAPIFY(A, largest)
we can characterize the running time of MAX-HEAPIFY on a node of height h as O(h).
Building a heap
We can use the procedure MAX-HEAPIFY in a bottom-up manner to convert an array A[1...n], where n = length[A], into a max-heap.The elements in the subarray A[(⌊n/2⌋+1)...n] are all leaves of the tree, and so each is a 1-element heap to begin with. The procedure BUILD-MAX-HEAP goes through the remaining nodes of the tree and runs MAX-HEAPIFY on each one.
BUILD-MAX-HEAP(A)
1 heap-size[A] ← length[A]
2 for i ← ⌊length[A]/2⌋ downto 1
3 do MAX-HEAPIFY(A, i)
The heapsort algorithm
The heapsort algorithm starts by using BUILD-MAX-HEAP to build a max-heap on the inpuarray A[1...n], where n = length[A]. Since the maximum element of the array is stored at theroot A[1], it can be put into its correct final position by exchanging it with A[n]. If we now "discard" node n from the heap (by decrementing heap-size[A]), we observe that A[1 ...(n - 1)] can easily be made into a max-heap. The children of the root remain max-heaps, but the new root element may violate the max-heap property. All that is needed to restore the max-heap property, however, is one call to MAX-HEAPIFY(A, 1), which leaves a max-heap in A[(n - 1)]. The heapsort algorithm then repeats this process for the max-heap of size n - 1 down to a heap of size 2.
HEAPSORT(A)
1 BUILD-MAX-HEAP(A)
2 for i ← length[A] downto
3 do exchange A[1] ↔ A[i
4 heap-size[A] ← heap
5 MAX-HEAPIFY(A, 1)
程序模拟
#include <iostream>
using std::cin;
using std::cout;
unsigned int GetLchild(unsigned int iPos)
{//注:堆排序中的树是完全2叉树,如果父亲节点是iPos那么左孩子是2 * iPos
return 2 * iPos;
}
unsigned int GetRchild(unsigned int iPos)
{//注:堆排序中的树是完全2叉树,如果父亲节点是iPos那么右孩子是2 * iPos + 1
return 2 * iPos + 1;
}
void Swap(int &a, int &b)
{//值交换
int temp = a;
a = b;
b = temp;
}
void MaxHeapify(int * iArry, unsigned int iPos)
{//父亲节点和儿子节点比较和交换
int iLchild = GetLchild(iPos);
int iRchild = GetRchild(iPos);
int iLargest = iPos;
if (iLchild <= iArry[0] && iArry[iLchild] > iArry[iPos]) iLargest = iLchild;
if (iRchild <= iArry[0] && iArry[iRchild] > iArry[iLargest]) iLargest = iRchild;
if (iLargest != iPos){
Swap(iArry[iLargest], iArry[iPos]);
MaxHeapify(iArry, iLargest);//递归把原iPos的值放到合适的位置
}
}
void BuildMaxHeap(int * iArry)
{//自底向上建立大顶堆
//由于是完全2叉树,所以节点 n / 2 + 1到 n 的节点都是叶子节点
//我们建堆得时候只需要从最后的节点n / 2开始到根节点调整即可
for (unsigned int iPos = iArry[0] / 2; iPos != 0; --iPos){
MaxHeapify(iArry, iPos);
}
}
void HeapSort(int * iArry)
{//进行堆排序,每次把最后一个未排序的跟根节点(最大的)交换
//实现从小到大排序
BuildMaxHeap(iArry); //建立大顶堆
for (unsigned int iPos = iArry[0]; iPos >= 1; --iPos){
Swap(iArry[1], iArry[iPos]);
iArry[0]--;
MaxHeapify(iArry, 1);
}
}
int main(void)
{
unsigned int iLen;
while (cin >> iLen){
int * iArry = new int [iLen + 1];
if (iLen == 0) return 0;
iArry[0] = iLen;
for (unsigned int i = 1; i <= iLen; ++i) cin >> iArry[i];
HeapSort(iArry);
for (unsigned int i = 1; i <= iLen; ++i) cout << iArry[i] << ' ';
cout << '/n';
delete []iArry;
}
return 0;
}
//写的...好烂...