1. 程式人生 > 其它 >SGI STL優先佇列priority_queue

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;
}