SGI STL优先队列priority_queue

priority_queue简介

跟普通queue不同的是,priority_queue拥有权值的概念,允许加入新元素、移除旧元素、查看元素值等。priority_queue本身也是一个queue,因此只允许在尾部加入元素,头部取出元素,除此外无法从别的位置存取元素。

普通queue是按先进先出的规则取出元素,内部存储顺序也是按进入先后顺序排列;priority_queue并非如此排列,而是自动按元素的权值排列。权值最高值,排在最前面。

默认情况,priority_queue用一个max-heap实现,而priority_queue是以vector作为底部容器表现的complete binary tree(完全二叉树)。因为max-heap可以满足priority_queue所需的“依赖权值高低自动排序”的特性。

priority_queue数据结构

类似于stack、queue,priority_queue也是以底部容器完成操作的,加上heap处理规则。因此,STL中priority_queue往往不被归类为container(容器),而被归类为container adapter(容器适配器)。

#   define __STL_DEPENDENT_DEFAULT_TMPL(_Tp) = _Tp

// 优先队列
template <class _Tp,
          class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(vector<_Tp>),
          class _Compare
          __STL_DEPENDENT_DEFAULT_TMPL(less<typename _Sequence::value_type>) >
class priority_queue {
public:
  // 内嵌类型定义
  typedef typename _Sequence::value_type      value_type;
  typedef typename _Sequence::size_type       size_type;
  typedef          _Sequence                  container_type;

  typedef typename _Sequence::reference       reference;
  typedef typename _Sequence::const_reference const_reference;
protected:
  _Sequence c;   // 底层容器
  _Compare comp; // 比较子, 元素大小比较标准
public:
  priority_queue() : c() {}
  explicit priority_queue(const _Compare& __x) :  c(), comp(__x) {}

  // 以下任意构造函数都立刻于底层容器内产生一个implicit representation heap
  // 因为调用了make_heap
  priority_queue(const _Compare& __x, const _Sequence& __s)
    : c(__s), comp(__x)
    { make_heap(c.begin(), c.end(), comp); }

  priority_queue(const value_type* __first, const value_type* __last)
    : c(__first, __last) { make_heap(c.begin(), c.end(), comp); }

  priority_queue(const value_type* __first, const value_type* __last,
                 const _Compare& __x)
    : c(__first, __last), comp(__x)
    { make_heap(c.begin(), c.end(), comp); }

  priority_queue(const value_type* __first, const value_type* __last,
                 const _Compare& __x, const _Sequence& __c)
    : c(__c), comp(__x)
  {
    c.insert(c.end(), __first, __last);
    make_heap(c.begin(), c.end(), comp);
  }

  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  const_reference top() const { return c.front(); }
  void push(const value_type& __x) {
    __STL_TRY {
      // push_heap 是泛型算法, 先利用底层容器的push_back()将新元素
      // 推入末端, 再重排heap
      c.push_back(__x);
      push_heap(c.begin(), c.end(), comp); // 泛型算法
    }
    __STL_UNWIND(c.clear()); // commit or clear all
  }
  void pop() {
    __STL_TRY {
      // pop_heap 是泛型算法, 从heap内取出一个元素. 不是真正将元素弹出, 而是重排heap,
      // 然后再以底层容器的pop_back() 取得被弹出的元素.
      pop_heap(c.begin(), c.end(), comp);
      c.pop_back();
    }
    __STL_UNWIND(c.clear()); // commit or clear all
  }
};

#   define __STL_TRY try
#   define __STL_CATCH_ALL catch(...)
#   define __STL_THROW(x) throw x
#   define __STL_RETHROW throw
#   define __STL_NOTHROW throw()
#   define __STL_UNWIND(action) catch(...) { action; throw; }

priority_queue测试实例

#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
       { // test case1: test priority_queue
              int ia[9] = { 0,1,2,3,4,8,9,3,5 };
              priority_queue<int> ipq{ ia, ia + 9 };
              cout << "size = " << ipq.size() << endl; // size = 9
              for (size_t i = 0; i < ipq.size(); i++) {
                     cout << ipq.top() << ' '; // 9 9 9 9 9 9 9 9 9
              }
              cout << endl;
              while (!ipq.empty()) {
                     cout << ipq.top() << ' '; // 9 8 5 4 3 3 2 1 0
                     ipq.pop();
              }
              cout << endl;
       }
       return 0;
}
posted @ 2022-05-09 14:36  明明1109  阅读(63)  评论(0编辑  收藏  举报