堆排序是一种将二叉树的结构运用于数组的效率很好的排序方法。
第一步,数组除了0号元素不满足最大堆的条件,其他位置都已经满足,那么需要调整整个数组到满足最大堆的状态。前提条件是除了0号元素,其他的元素都已经满足了最大堆的要求,也就是说0号元素的左右子树都是最大堆,那么只需要比较0号元素和它的左右孩子结点的大小,如果已经大于等于它的左右子节点,那么已经是最大堆了,如果0号元素小于它的左或者右子节点,则将0号元素和左右子节点中大的一个互换,这时候0号元素还有它的左子树(假设之前是和右子节点互换的)都满足了最大堆的条件,而新的右子树不一定满足,因此需要递归的对新的右子树来调整。
void InsertHeap(int* pData,int low,int high)
{
int large = low*2+1;
while(large <= high)
{
if(large < high && pData[large] < pData[large+1])
++large;
if(pData[low] < pData[large])
Swap(pData,low,large);
else
break;
low = large;
large = 2*low+1;
}
}
第二步,利用第一步的方法,对整个数组来建立最大堆,因为数组后半部分的元素都是只含有一个结点的子树,而含有一个结点的二叉树本身就是最大堆,因此我们从数组的前半部分的第一个非叶子节点开始建堆,然后逐个往前直到0号元素:
void BuildHeap(int* pData,int size)
{
for(int i=size/2-1;i>=0;--i)
{
InsertHeap(pData,i,size-1);
}
}
void HeapSort(int* pData,int size)
{
if(size > 1)
{
BuildHeap(pData,size);
for(int lastUnSorted = size-1; lastUnSorted > 0; --lastUnSorted)
{
Swap(pData, 0, lastUnSorted);
InsertHeap(pData,0,lastUnSorted - 1);
}
}
}
void Swap(int* pData, int source,int target)
{
if(source != target)
{
int temp = pData[source];
pData[source] = pData[target];
pData[target] = temp;
}
}