[数据结构】二叉堆

参考:《漫画算法-小灰的算法之旅》

目录

一、什么是二叉堆

二、二叉堆的操作

1、插入节点

2、删除节点

3、构建而二叉堆

三、时间复杂度和空间复杂度

四、二叉堆的存储方式


一、什么是二叉堆

二叉堆本质上是一种完全二叉树,它分为两类:最大堆和最小堆。最大堆的任何一个父节点的值都大于或等于它左右孩子节点的值;最小堆的任何一个父节点的值,都小于或等一它左右孩子节点的值。

二叉堆的根节点叫做栈顶。最大堆和最小堆的特点决定了:最大堆的堆顶是整个堆中的最大元素;最小堆的堆顶是整个堆中的最小元素。

二、二叉堆的操作

对于二叉堆有下面几种操作:插入节点、删除节点、构建二叉堆。这几种操作都基于堆的自我调整。所谓堆的自我调整,就是把一个不符合堆性质的完全二叉树,调整为一个堆。以下皆以最小堆为例。

1、插入节点

当插入一个节点时插入位置是完全二叉树的最后一个位置。例如插入一个新节点,值是0。

 新节点的父节点5比0大,不符合堆的性质。于是让新节点上浮,和父节点交换位置。

 继续用节点0和父节点3做比较,因为0小于3,则让新节点继续“上浮”。

 继续比较,最终新节点0“上浮”到了堆顶位置。

2、删除节点

二叉堆删除节点的过程和插入节点的过程正好相反,所删除的是处于堆顶的节点。例如删除最小堆的堆顶节点1。

 为了继续维持完全二叉树的结构,我们把 堆的最后一个节点10临时补到原本堆顶的位置。

让暂处堆顶位置的节点10和它的左、右 孩子进行比较,如果左、右孩子节点中最小的一个 (显然是节点2)比节点10小,那么让节点10“下沉”。

继续让节点10和它的左、右孩子做比较,左、右 孩子中最小的是节点7,由于10大于7,让节点10继续 “下沉”。

3、构建而二叉堆

构建二叉堆,也就是把一个无序的完全二叉树调整为二叉堆,本质就是让所有非叶子节点依次下沉。

例子:

首先,从最后一个非叶子结点开始,也就是从节点10开始。如果节点10大于它左、右孩子节点中最小 的一个,则节点10“下沉”。

接下来轮到节点3,如果节点3大于它左、右孩子 节点中最小的一个,则节点3“下沉”。

然后轮到节点1,如果节点1大于它左、右孩子节点中最小的一个,则节点1“下沉”。事实上节点1小于它的左、右孩子,所以不用改变。 接下来轮到节点7,如果节点7大于它左、右孩子节点中最小的一个,则节点7“下沉”。

 节点7继续比较,继续“下沉”。

经过上述几轮比较和“下沉”操作,最终每一节 点都小于它的左、右孩子节点,一个无序的完全二叉 树就被构建成了一个最小堆。

三、时间复杂度和空间复杂度

堆的插入操作是单一节点的“上浮” ,堆的删除操作是单一节点的“下沉” ,这两个操作的平均交换次数都是堆高度的一半,所以时间复杂度是 O(logn)。构建堆的时间复杂度却并不是O(n)。

四、二叉堆的存储方式

二叉堆虽然是一个完全二叉树,但是它的存储方式并不是并不是链式存储,而是顺序存储。换句话说,二叉堆的所有节点都存储在数组中。

在数组中,在没有左、右指针的情况下,如何定位一个父节点的左孩子和右孩子呢? 像上图那样,可以依靠数组下标来计算。 假设父节点的下标是parent,那么它的左孩子下标就是 2×parent+1; 右 孩 子 下 标 就 是 2×parent+2。

猜你喜欢

转载自blog.csdn.net/weixin_45922730/article/details/129711217