原文连接:https://jiang-hao.com/articles/2020/algorithms-algorithms-heap-sort.htmlhtml
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似彻底二叉树的结构,并同时知足堆积的性质:即子结点的键值或索引老是小于(或者大于)它的父节点。堆排序能够说是一种利用堆的概念来排序的选择排序。分为两种方法:java
堆排序的平均时间复杂度为 Ο(nlogn)。算法
一般堆是经过一维数组来实现的。在数组起始位置为0的情形中:api
在堆的数据结构中,堆中的最大值老是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义如下几种操做:数组
首先第一步和第二步,建立堆,这里咱们用最大堆;建立过程当中,保证调整堆的特性。数据结构
从最后一个分支的节点开始从右往左,从下至上进行调整为最大堆。svg
如今获得的最大堆的存储结构以下:测试
初始堆建立完成。ui
接着,最后一步,堆排序,进行(n-1)次循环。this
持续整个过程直至最后一个元素为止。
这个迭代持续直至最后一个元素即完成堆排序步骤。
public class HeapSort { private int[] arr; public HeapSort(int[] arr) { this.arr = arr; } /** * 堆排序的主要入口方法,共两步。 */ public void sort() { /* * 第一步:将数组堆化 * beginIndex = 第一个非叶子节点。 * 从第一个非叶子节点开始便可。无需从最后一个叶子节点开始。 * 叶子节点能够看做已符合堆要求的节点,根节点就是它本身且本身如下值为最大。 */ int len = arr.length - 1; int beginIndex = (arr.length >> 1)- 1; for (int i = beginIndex; i >= 0; i--) maxHeapify(i, len); /* * 第二步:对堆化数据排序 * 每次都是移出最顶层的根节点A[0],与最尾部节点位置调换,同时遍历长度 - 1。 * 而后重新整理被换到根节点的末尾元素,使其符合堆的特性。 * 直至未排序的堆长度为 0。 */ for (int i = len; i > 0; i--) { swap(0, i); maxHeapify(0, i - 1); } } private void swap(int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } /** * 调整索引为 index 处的数据,使其符合堆的特性。 * * @param index 须要堆化处理的数据的索引 * @param len 未排序的堆(数组)的长度 */ private void maxHeapify(int index, int len) { int li = (index << 1) + 1; // 左子节点索引 int ri = li + 1; // 右子节点索引 int cMax = li; // 子节点值最大索引,默认左子节点。 if (li > len) return; // 左子节点索引超出计算范围,直接返回。 if (ri <= len && arr[ri] > arr[li]) // 先判断左右子节点,哪一个较大。 cMax = ri; if (arr[cMax] > arr[index]) { swap(cMax, index); // 若是父节点被子节点调换, maxHeapify(cMax, len); // 则须要继续判断换下后的父节点是否符合堆的特性。 } } /** * 测试用例 * * 输出: * [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9] */ public static void main(String[] args) { int[] arr = new int[] {3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6}; new HeapSort(arr).sort(); System.out.println(Arrays.toString(arr)); } }