这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
介绍
堆结构就是用数组实现的完全二叉树结构,也叫做优先级队列结构,堆排序是利用堆这种数据结构而设计的一种排序算法, 堆排序是一种选择排序, 它的最坏, 最好平均时间复杂度均为 O(nlogn), 它也是不稳定排序。
堆是具有以下性质的完全二叉树: 每个结点的值都大于或等于其左右孩子结点的值, 称为大顶堆(注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系,)每个结点的值都小于或等于其左右孩子结点的值, 称为小顶堆。
思路
1.首先我们来看构建大顶堆的两个主要方法:
heapInsert: 向堆中加入元素,先加在末尾,然后通过比较其与父节点之间的大小关系不断向上交换。直到子节点的值小于父节点。
heapify: 将以index位置为根节点的树调整为大根堆的形式
注意: 以上方法也可以构建小根堆,只是条件稍微改变一下
2.通过heapInsert首先将数组构成一个大根堆
3.整个序列的最大值就是堆顶的根节点。
4.将其与末尾元素进行交换, 此时末尾就为最大值
5.然后将剩余 n-1 个元素通过heapify重新构造成一个堆, 这样会得到 n 个元素的次小值。 如此反复执行, 便能得到一个有序序列了
代码
1 | java复制代码 public void heapSort(int[] arr) { |
堆排序扩展题目
已知一个几乎有序的数组, 几乎有序是指, 如果把数组排好顺序的话, 每个元素移动的距离可以不超过k, 并且k相对于数组来说比较小。 请选择一个合适的排序算法针对这个数据进行排序。
思路
1.可以使用一个容量为k+1个小根堆进行操作,
2.将数组中索引位置为i到i+k上面的k+1个元素加入到小根堆中,将堆顶的最小值放到i位置上
3.此时<=i位置的元素已经排序好了然后把k+2上面的元素加入到小根堆中,继续重复操作
4.添加到arr.length-1位置元素的时候把直接把堆中元素弹出放到对应位置即可。
1 | java复制代码public void sortArrayDistanceLessK(int[] arr, int k) { |
时间复杂度
O(N * logN)
headInsert和heapify的时间复杂度都是logN
1 | java复制代码 for (int i = arr.length - 1; i >= 0; i--) { //这个是O(N * logN)级别的 |
for循环遍历一遍元素然后heapify的时间复杂度为logN所以堆排序的时间复杂度为O(N * logN)
额外空间复杂度
O(1)
只用到有限几个变量
本文转载自: 掘金