堆排序的建堆过程是核心步骤,其核心思想是通过调整使数组满足堆的性质。以下是详细的建堆方法和注意事项:
完全二叉树表示
将数组元素按完全二叉树结构存储,根节点为索引0,左孩子节点为$2i+1$,右孩子节点为$2i+2$,父节点为$lfloor i/2 rfloor$。
从最后一个非叶子节点开始调整
调整过程从最后一个非叶子节点开始,向前递归调整每个节点,确保每个子树满足堆的性质。 - 非叶子节点判断 :最后一个非叶子节点的索引为$lfloor n/2 rfloor - 1$(其中$n$为数组长度)。
调整过程(siftdown)
选择当前节点与其左右孩子中值最大的节点进行交换;
若交换后当前节点小于其最大孩子节点,则继续调整该孩子节点,直到满足堆的性质。
以数组$A = {1, 3, 4, 5, 7, 2, 6, 8, 0}$为例:
初始化堆 :将元素按完全二叉树填充,得到初始结构。
调整节点 :从索引2(值5)开始,依次调整每个节点:
节点2与孩子节点7和8比较,交换后数组变为${1, 3, 8, 5, 7, 2, 6, 4, 0}$;
节点6与孩子节点2和8比较,交换后数组变为${1, 3, 8, 5, 7, 0, 6, 4, 2];
继续调整其他节点,最终得到大根堆结构${7, 10, 8, 5, 6, 2, 4, 3, 0}$。
最坏情况 :每次调整需遍历树的高度,时间复杂度为$O(log n)$,总调整次数为$O(n)$,因此建堆时间复杂度为$O(n log n)$。
优化方法 :从最后一个非叶子节点开始调整,可减少递归深度,但时间复杂度仍为$O(n log n)$。
堆类型选择 :
大根堆:根节点为最大值,调整时保证父节点≥子节点;
小根堆:根节点为最小值,调整时保证父节点≤子节点。
交换操作 :交换后需重新调整受影响的子树,确保整体堆性质。
边界条件 :
当数组长度为1时,无需调整;
调整过程中需注意数组越界(如左孩子索引$2i+1$可能超过数组长度)。
通过以上方法,可高效完成堆排序的建堆过程,为后续排序步骤奠定基础。