欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-31 19:09:06
...

参考: 《STL源码剖析》

 

heap概述

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

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

完全二叉树整棵树内没有任何节点漏洞,这带来一个好处:我们可以利用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最小堆)

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

SGI STL:

incline void push_heap(RandomAccessIterator first,
                       RandomAccessIterator last);

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

2)pop_heap算法

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

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

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)make_heap算法

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