基本概念
堆(Heap)是一种完全二叉树结构,同时满足 “堆性质”:
- 大根堆(Max Heap):每个父节点的值 大于或等于 其左右子节点的值,堆顶(根节点)是整个堆的最大值。
- 小根堆(Min Heap):每个父节点的值 小于或等于 其左右子节点的值,堆顶是整个堆的最小值。
堆的数据结构
堆通常用数组存储(完全二叉树适合数组表示,无需额外指针)。若数组索引从0开始,对于节点索引 i:
- 左孩子节点索引:2*i+1
- 右孩子节点索引:2*i+2
- 孩子节点找父亲:(i-1)/2
堆排序的步骤
以升序为例
- 创建大根堆
从最后一个非叶子节点(索引为 n/2-1 )开始向上调整,从后往前对每个节点做堆调整 - 交换堆顶和堆尾元素,调整堆
因为要实现升序排列,所以采用的是**“大根堆+向下调整算法”**的模式,关于创建大根堆和算法的实现留在代码实现部分讲解
代码实现
void AdjustDown(int arr[], int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 < n && arr[child] < arr[child + 1])
{
child++; // 假设法 找出俩孩子里小的那个
}
if (arr[parent] < arr[child])
{
swap(arr[child], arr[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int arr[], int n)
{
// 先建堆
for (int i = (n - 2) / 2; i >= 0; --i)
{
AdjustDown(arr, n, i);
}
for (int i = n - 1; i > 0; --i)
{
swap(arr[0], arr[i]);
AdjustDown(arr, i, 0);
}
}
- 建堆
建堆选择从最后一个非叶子节点开始的原因是:叶子节点没有子节点,因此单个叶子节点本身就满足 “堆性质” - 向下调整算法
什么时候用向下调整算法?当调整的节点其子树已经为堆时就用向下调整算法
分析
其实堆排序的难点不在排序上,而在你是否对二叉树和堆有了解,了解过后实现排序就是看一遍代码的事情.
堆排序的时间复杂度为O(N*log2N)(这里是以2为底),分别是构建堆O(N)和向下调整算法O(log2N)
堆排序是不稳定的排序算法。因为调整堆时,相同值的元素相对位置可能被交换
总结
堆排序利用大顶堆 / 小顶堆特性,通过 “构建堆 + 交换调整” 完成排序。它的时间复杂度稳定为O(n log n),空间复杂度O(1),是高效的原地排序算法,但稳定性不足。适合对性能要求高、不严格要求稳定性的场景(如大规模数据排序)。
682

被折叠的 条评论
为什么被折叠?



