堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
算法思想(以大顶堆为例):
1.将长度为n的待排序的数组进行堆有序化构造成一个大顶堆
2.将根节点与尾节点交换并输出此时的尾节点
3.将剩余的n -1个节点重新进行堆有序化
4.重复步骤2,步骤3直至构造成一个有序序列
这里的大根堆(最上面的节点最大),看可以看成一个完全二叉树,永远将最大的元素维护在堆顶。
堆可以被看成是一棵树,结点在堆中的高度可以被定义为从本结点到叶子结点的最长简单下降路径上边的数目;定义堆的高度为树根的高度。我们将看到,堆结构上的一些基本操作的运行时间至多是与树的高度成正比,为O(lgn)。
//堆排序
//整理节点time:O(lgn)
template<typenameT>
void MinHeapify(T*arry, int size, int element)
{
int lchild = element * 2 + 1, rchild = lchild + 1;//左右子树
while (rchild < size)//子树均在范围内
{
if (arry[element] <= arry[lchild] && arry[element] <= arry[rchild])//如果比左右子树都小,完成整理
{
return;
}
if (arry[lchild] <= arry[rchild])//如果左边最小
{
swap(arry[element], arry[lchild]);//把左面的提到上面
element = lchild;//循环时整理子树
}
else//否则右面最小
{
swap(arry[element], arry[rchild]);//同理
element = rchild;
}
lchild = element * 2 + 1;
rchild = lchild + 1;//重新计算子树位置
}
if (lchild < size&&arry[lchild] < arry[element])//只有左子树且子树小于自己
{
swap(arry[lchild], arry[element]);
}
return;
}
//堆排序time:O(nlgn)
template<typenameT>
void HeapSort(T*arry, int size)
{
int i;
for (i = size - 1; i >= 0; i--)//从子树开始整理树
{
MinHeapify(arry, size, i);
}
while (size > 0)//拆除树
{
swap(arry[size - 1], arry[0]);//将根(最小)与数组最末交换
size--;//树大小减小
MinHeapify(arry, size, 0);//整理树
}
return;
}