heap(max-heap最大堆、min-heap最小堆)

参考: 《STL源码剖析》

 

heap概述

heap并不归属于STL容器组件,它是个幕后英雄,扮演priority_queue的助手(底层实现)。所谓binary heap就是一种完全二叉树,也就是说,整颗binary tree除了最底层的叶子节点之外,是填满的,而最底层的叶节点由左至右又不得有空隙。

heap(max-heap最大堆、min-heap最小堆)_第1张图片

完全二叉树整棵树内没有任何节点漏洞,这带来一个好处:我们可以利用array来存储所有节点。假设我们动用一个小技巧,将array的#0元素保留(或设为无限大值或无限小值),那么完全二叉树中的某个节点位于array的i处时,其左子节点位于array的2i处,其右子节点位于array的2i+1处,其父节点位于“i/2".

最大堆max-heap:每个节点的键值(key)都大于或等于其子节点键值

最小堆min-heap:每个节点的键值(key)都小于或等于其子节点键值

heap算法

1)push_heap算法

新元素插入到底层vector的end()处,然后对最底端元素执行“上溯程序”。时间复杂度O(logN)。

heap(max-heap最大堆、min-heap最小堆)_第2张图片

算法思路:新元素是否适合于现有位置?为满足max-heap的条件(每个节点的键值都大于或等于其子节点键值),我们执行一个所谓的上溯程序:将新节点拿来与其父节点比较,如果其键值比父节点大,就父子对换位置。如此一直上溯,直到不需要对换或直到根节点为止。

SGI STL:

incline void push_heap(RandomAccessIterator first,
                       RandomAccessIterator last);

注意,此函数被调用时,新元素应已置于底层容器的最底端

2)pop_heap算法

堆顶元素和最底端元素交换,缩小堆长,对堆顶执行“下溯程序”。时间复杂度为O(logN)。

heap(max-heap最大堆、min-heap最小堆)_第3张图片

inline void pop_heap(RandomAccessIterator first,
                     RandomAccessIterator last);

注意:该函数接受两个迭代器,用来表现一个heap底层容器vector的头尾。

3)sort_heap算法

既然每次pop_heap都获得heap中键值最大的元素,如果持续对整个heap做pop_heap操作,每次将操作范围从后向前缩减一个元素(因为pop_heap会把键值最大的元素放在底层容器的最底端),当整个程序执行完毕时,我们便有了一个递增序列。时间复杂度O(NlogN)。

heap(max-heap最大堆、min-heap最小堆)_第4张图片

4)make_heap算法

  1. 将N个元素按输入顺序存入,先满足完全二叉树的结构特性。
  2. 调整各节点位置,以满足最大堆的堆序性。这样创建最小堆时的时间代价为O(N)。在调整节点位置时,只需对从第N/2个节点到第一个节点依次应用“下溯”程序即可,其实也就是进行了N/2次的近似删除操作。

 

你可能感兴趣的:(STL源码剖析)