直观理解:二叉堆和堆排序(Heap)

  堆(Heap)是计算机中一种特殊的数据结构,通常可以看成一个完全二叉树的数组对象【如果一个二叉树的深度为,除第 层外,其它各层 () 的结点数都达到最大个数,第 层所有的结点都连续集中在最左边,这就是完全二叉树】,堆根据堆顶存储的是最大元素还是最小元素,可以分为大根堆和小根堆。堆具有下列性质:

  • 堆中每个节点的值总是不大于(Max-heap)或者不小于(Min-heap)其父节点的值。
  • 堆总是一颗完全二叉树。

  由于堆满足完全二叉树的结构,因此可以用一个下表从1开始的数组来存储堆结构的内容,其中节点存储在下标的两个子节点分别存放在下标为的位置中,而下标为的节点的父节点的下标为。如下图所示:

Max Heap

  假设当前元素的索引位置为 i,可以得到规律:

parent(i) = i / 2;
left_child(i) = 2 * i;
right_child(i) = 2 * i + 1;

  下面以大根堆为例,详细介绍堆的两个最基本的操作Shift Up和Shif Down的过程。

Shift Up

  向一个堆中插入一个元素的过程称之为shift up,首先将新插入的元素放在完全二叉树的最后一个位置,每次shift up时需要将当前节点与其父节点进行比较,如果当前节点大于其父节点,则交换当前节点和父节点的位置。直到当前节点不大于父节点为止。整个过程如下:

append new node
shift up
shift up and finished

Shift Down

  上面介绍了如何向一个堆中添加元素的过程,接下来介绍,如果移除堆顶的元素。移除堆顶元素的过程称为Shift Down,每一次移除堆顶元素时,需要用完全二叉树的最后一个元素进行补位,即将最后一个节点放在堆顶的位置,然后通过不断shift down操作,使得堆当前二叉树终满足堆的结构。每次shift down的时候需要将当前节点与其最大的叶子节点进行交换,不断重复这个过程,直到不能交换为止。

remove root
replace
shift down
shift down and finished

Heapify

  之前我们介绍到的Shift Up是通过,每次向构建好的堆中插入一个节点之后,进行堆化(Heapify)的过程,如果现在有一个已经给定的数组,怎么将其调整成一个符合条件的堆呢?这个调整的过程称之为堆化(Heapify)。堆化的过程其实也非常简单,就是从最后一个非叶子节点开始,依次倒序对每个非叶子节点执行Shift down的过程,每次执行完一个顶点之后,倒序找到下一个非叶子节点执行Shift Down的过程,直到最后对根节点执行完Shift Down,此时就能得到一个符合条件的堆。堆化的过程如下图所示:

original
step 1 shift down
step 2 shift down
step 3 shift down
step 4 shift down
step 5 shift down
finished

  至此,我们对堆进行了简单直观的介绍,二叉堆没有任何神秘的地方,主要操作也就是shift up和shift down,堆是一种非常有用的数据结构,通常用来实现优先级队列,在时间复杂度上,不论是shift up和shift down,最大时间复杂度也就是,因此,基于堆实现的优先级队列的追加和删除元素的实践复杂度都是。以上就是堆的基本内容。

你可能感兴趣的:(直观理解:二叉堆和堆排序(Heap))