算法导论阅读笔记3-堆排序

2018-09-21  本文已影响10人  二进制研究员

算法描述

堆排序(heapsort)与归并排序一样,但不同于插入排序的是,其时间复杂度为O(nlgn)。而与插入排序相同,但不同于归并排序的是,堆排序同样具有空间原址性:任何时候只需要常数个额外的元素空间存储临时数据。
在堆排序算法中,我们使用的是最大堆。最小堆通常用于构造优先队列。
(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树。除了最底层外,该树是完全充满的,而且是从左到右填充。表示堆的数组A包含两个属性:A.length(通常)给出数组元素的个数,A.heap-size表示有多少个堆元素存储在该数组中。也就是说,虽然A[1..A.length]可能都存有数据,但只有A[1..A.heap-size]中存放的是堆的有效元素,这里,0≤A.heap-size≤A.length。

维护堆的性质

MAX-HEAFIFY用于维护最大堆的性质。它的输入为一个数组和一个下标i。在调用MAX-HEAPIFY的时候,我们假定根节点为LEFT(i)和RIGHT(i)的二叉树都是最大堆,但这是A[i]有可能小于其孩子,这违背了最大堆的性质。MAX-HEAPIFY通过让A[i]的值在最大堆中“逐级下降”,从而使得以下标i为根节点的子树重新遵循最大堆的性质。

MAX-HEAPIFY(A, i)
l = LEFT(i)
r = RIGHT(i)
if l <= A.heap-size and A[l] > A[i]
  largest = l
else
  largest = i
if r <= A.heap-size and A[r] > A[largest]
  largest = r
if largest != i
  exchange A[i] with A[largest]
  MAX-HEAPIFY(A, largest)
MAX-HEAPIFY示例

时间复杂度为O(lgn),即O(h)。

建堆

可以用自底向上的方法利用过程MAX-HEAPIFY把一个大小为n=A.length的数组A[1..n]转换为最大堆。子数组A(\lfloor{n/2}\rfloor+1..n)中的元素都是树的叶子节点。每个叶节点都可以看成只包含一个元素的堆。过程BUILD-MAX-HEAP对树中的其它节点都调用一次MAX-HEAPIFY。

BUILD-MAX-HEAP(A)
A.heap-size = A.length
for i = A.length/2 downto 1
  MAX-HEAPIFY(A, i)

时间复杂度: O(n)。

构建堆的示例

堆排序算法

初始时,堆排序算法利用BUILD-MAX-HEAP将输入数组A[1..n]建成最大堆,其中n=A.length。因为数组中的最大元素总在根节点A[1]中,通过把它与A[n]进行互换,我们可以让该元素放到正确的位置。这时,如果我们从堆中去掉节点n(通过减少A.heap-size的值实现),剩余的节点中,原来根的孩子节点仍然是最大堆,而新的根节点可能会违背最大堆的性质。为了维护最大堆的性质,我们要做的是调用MAX-HEAPIFY(A, 1),从而在A[1..n-1]上构造一个新的最大堆。最排序算法会不断重复这一过程,直到堆的大小从n-1降到2。

HEAPSORT(A)
BUILD-MAX-HEAP(A)
for i = A.length downto 2
  exchange A[1] with A[i]
  A.heap-size = A.heap-size - 1
  MAX-HEAPIFY(A, 1)
HEAPSORT运行过程(部分)

优先级队列

优先级队列是一种用来维护由一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字。一个最大优先级队列支持以下操作:

HEAP-MAXIMUM(A)
return A[1]

时间复杂度Θ(1)。

HEAP-EXTRACT-MAX(A)
if A.heap-size < 1
  error "heap underflow"
max = A[1]
A[1] = A[A.heap-size]
A.heap-size = A.heap-size - 1
MAX-HEAPIFY(A, 1)
return max

时间复杂度为O(lgn)。

HEAP-INCREASE-KEY(A, i, key)
if key < A[i]
  error "new key is smaller than current key"
A[i] = key
while i > 1 and A[PARENT(i)] < A[i]
  exchange A[i] with A[PARENT(i)]
  i = PARENT(i)

时间复杂度为O(lgn).

MAX-HEAP-INSERT(A, key)
A.heap-size = A.heap-size + 1
A[A.heap-size] = -INF
HEAP-INCREASE-KEY(A, A.heap-size, key)

运行时间O(lgn)。

特性:

堆排序为非稳定排序

上一篇下一篇

猜你喜欢

热点阅读