make_heap, push_heap, pop_heap, 的使用

stl make_heap使用

摘要:好久没有写blog,翻译一篇cplusplus上的make heap文档,凑凑数吧。在工程项目中有不少需求是多次求最大数或者最小数,堆是好的选择之一。如果我比较懒,又比较严谨的话,项目也允许使用stl的话,我会采用STL的make_heap, push_heap, pop_heap, sort_heap, 结合vector来完成需求。

  • Make heap
template <class RandomAccessIterator>
  void make_heap ( RandomAccessIterator first, RandomAccessIterator last );
 
template <class RandomAccessIterator, class Compare>
  void make_heap ( RandomAccessIterator first, RandomAccessIterator last,
                   Compare comp );

根据随机迭代器first和last指定的范围[first,last)创建一个大顶堆(最大的元素*first在上面,也可以说在容器的front端)。大顶堆的性质是上面的元素总比其两个子节点元素大。在构造堆的过程中,第一个函数使用‘<’进行比较,第二个模板函数使用comp仿函数进行比较。

利用make_heap构造堆后,可以利用vector::push_back配合push_heap把一个元素添加到堆中,利用pop_heap和vector::pop_back删除堆顶的元素(再唠叨句:堆顶元素位于vector的front),仍然得到一个大顶堆。

    • 例子
// range heap example
#include 
#include 
#include 
using namespace std;
 
int main () {
  int myints[] = {10,20,30,5,15};
  vector<int> v(myints,myints+5);
 
  make_heap (v.begin(),v.end());
  cout << "initial max heap   : " << v.front() << endl;
 
  pop_heap (v.begin(),v.end()); v.pop_back();
  cout << "max heap after pop : " << v.front() << endl;
 
  v.push_back(99); push_heap (v.begin(),v.end());
  cout << "max heap after push: " << v.front() << endl;
 
  sort_heap (v.begin(),v.end());
 
  cout << "final sorted range :";
  for (unsigned i=0; i<v.size(); i++) cout << " " << v[i];
 
  cout << endl;
 
  return 0;
}
    • 输出:
initial max heap   : 30
max heap after pop : 20
max heap after push: 99
final sorted range : 5 10 15 20 99
    • Complexity

At most, (3*(last-first)) comparisons.

  • push_heap
template <class RandomAccessIterator>
  void push_heap ( RandomAccessIterator first, RandomAccessIterator last );
 
template <class RandomAccessIterator, class Compare>
  void push_heap ( RandomAccessIterator first, RandomAccessIterator last,
                   Compare comp );

给定first和last的值,push_heap把last-1这个位置上的元素加入到堆中,最后[first,last)这个范围的元素仍然构成一个堆。

    • Complexity

At most, log(last-first) comparisons.也就是堆高。从堆底往上调整。如果孩子比父亲大,跟父亲交换位置即可。

  • pop_heap
template <class RandomAccessIterator>
  void pop_heap ( RandomAccessIterator first, RandomAccessIterator last );
 
template <class RandomAccessIterator, class Compare>
  void pop_heap ( RandomAccessIterator first, RandomAccessIterator last,
                   Compare comp );

把堆顶的元素移动到last-1的位置,然后调整堆,最后[first,last-1)仍然是一个堆。

    • Complexity

At most, (2*log(last-first)) comparisons.堆顶元素走了,他的两个儿子比较,谁大谁上来,如此继续比较,直到堆底。因此是2倍的log(last-first)

  • sort_heap
template <class RandomAccessIterator>
  void sort_heap ( RandomAccessIterator first, RandomAccessIterator last );
 
template <class RandomAccessIterator, class Compare>
  void sort_heap ( RandomAccessIterator first, RandomAccessIterator last,
                   Compare comp );

调整[first,last)返回的元素,即在容器vector中元素按照升序排列。注意[first,last)这个范围不在具有堆的性质。

    • Complexity

At most, NlogN comparisons, where N is (last-first).每次把堆顶元素放到vector的last-1, last-2, …,每次move堆顶元素后,都要调整一次堆。

你可能感兴趣的:(C++)