当前位置:   article > 正文

最小堆的时间复杂度_图解堆结构、堆排序及堆的应用

最小堆的时间复杂度

前言

这次我们介绍另一种时间复杂度为 O(nlogn) 的选择类排序方法叫做堆排序。

我将从以下几个方面介绍:

  • 堆的结构
  • 堆排序
  • 优化的堆排序
  • 原地堆排序
  • 堆的应用

堆的结构

什么是堆?我给出了百度的定义,如下:

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵 完全二叉树 的数组对象。

堆总是满足下列性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值。
  • 堆总是一棵完全二叉树。

将根节点最大的堆叫做最大堆,根节点最小的堆叫做最小堆。

下图展示了一个最大堆的结构:

d855d6e04b2fa03498e9f5ae68acdcbf.png

可见,堆中某个节点的值总是小于等于其父节点的值。

由于堆是一棵完全二叉树,因此我们可以对每一层进行编号,如下:

2c1f912de34752bfb34665b620d51372.png

我们完全可以使用数组存放这些元素,那如何确定存放的位置呢?利用如下公式:

父节点:parent(i) = (i-1)/2

左孩子:leftChild(i) = 2*i+1
右孩子:rightChild(i) = 2*i+2

相关代码如下:

private int parent(int index) {    return (index - 1) / 2;}private int leftChild(int index) {    return index * 2 + 1;}private int rightChild(int index) {    return index * 2 + 2;}

添加元素

向堆中添加元素的步骤如下:

  1. 将新元素放到数组的末尾。
  2. 获取新元素的父亲节点在数组中的位置,比较新元素和父亲节点的值,如果父亲节点的值小于新元素的值,那么两者交换。以此类推,不断向上比较,直到根节点结束。

下图展示了添加元素的过程:

64aa546077a94ef5bf73602f748d1dfa.png

添加元素的过程也叫做 siftUp ,代码如下:

// Array是自己实现的动态数组private Array data;public void add(E e) {    data.addLast(e);    siftUp(data.getSize() - 1);}private void siftUp(int k) {    while (k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0) {        data.swap(k, parent(k));        k = parent(k);    }}

删除元素

删除元素其实就是删除堆顶的元素,步骤如下:

  1. 让数组最后一个元素和数组第一个元素(堆顶元素)交换。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/734224
推荐阅读
相关标签
  

闽ICP备14008679号