堆排序是利用堆的思想来进行排序的
首先就是要建立一个堆。
如何建立?
答:将第一个数看作堆,后面的数依次插入堆(这里插入要利用向上调整算法)。
但是什么时构建小堆,什么是时候构建大堆?
排降序同理,故而得出结论:
- 排升序:建大堆。
- 排降序:建小堆。
【建堆的时间复杂度】
在讨论时间复杂度时,考虑的是最坏情况。堆是一个完全二叉树,建堆时向上调整,最坏的情况莫过于这个堆是一个满二叉树。因此此处使用满二叉树证明(时间复杂度考虑的本来就是近似值,多几个和少几个节点不影响结果)。
利用高中所学知识可计算,得:
【代码参考】
利用这个思想来实现堆排序,
排升序,建大堆。
// 升序
void HeapSort(int* a, int n)
{
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
adjustDown(a, n, i);
}
// 依次选数,调堆
// O(N*logN)
for (int end = n - 1; end > 0; --end)
{
swap(&a[end], &a[0]);
// 再调堆,选出次小的数
adjustDown(a, end, 0);
}
}
void adjustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
// 选出左右孩子中小的那一个
if (child + 1 < n && a[child + 1] < a[child])
{
++child;
}
// 如果小的孩子小于父亲,则交换,并继续向下调整
if (a[child] < a[parent])
{
swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void Swap(HPDataType* px, HPDataType* py)
{
HPDataType tmp = *px;
*px = *py;
*py = tmp;
}
排降序代码请自行实现。