1. 程式人生 > >STL原始碼分析之priority_queue優先順序佇列

STL原始碼分析之priority_queue優先順序佇列

前言

上一節分析heap其實就是為priority_queue做準備. priority_queue是一個優先順序佇列, 是帶權值的. 支援插入和刪除操作, 其只能從尾部插入,頭部刪除, 並且其順序也並非是根據加入的順序排列的. priority_queue因為也是佇列的一種體現, 所以也就跟佇列一樣不能直接的遍歷陣列, 也就沒有迭代器. priority_queue本身也不算是一個容器, 它是以vector為容器以heap為資料操作的配置器.

原始碼分析

型別定義

#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <
class T, class Sequence = vector<T>, class Compare = less<typename Sequence::value_type> > #else template <class T, class Sequence, class Compare> #endif class priority_queue { public: // 符合traits程式設計規範 typedef typename Sequence::value_type value_type; typedef typename Sequence:
:size_type size_type; typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; protected: Sequence c; // 定義vector容器的物件 Compare comp; // 定義比較函式(偽函式) ... };

建構函式

class  priority_queue {
	...
public:
  priority_queue() : c() {}	// 預設建構函式
  explicit priority_queue
(const Compare& x) : c(), comp(x) {} // 設定偽函式 #ifdef __STL_MEMBER_TEMPLATES // 接受以迭代器型別的引數 // 接受兩個迭代器以及函式. 傳入的迭代器範圍內表示的元素以comp定義的方式進行調整 template <class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x) : c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); } // 接受兩個迭代器. 傳入的迭代器範圍內表示的元素以預設的大根堆進行調整 template <class InputIterator> priority_queue(InputIterator first, InputIterator last) : c(first, last) { make_heap(c.begin(), c.end(), comp); } #else /* __STL_MEMBER_TEMPLATES */ // 接受兩個迭代器以及函式. 傳入的迭代器範圍內表示的元素以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) : c(first, last) { make_heap(c.begin(), c.end(), comp); } #endif /* __STL_MEMBER_TEMPLATES */ ... };

屬性獲取

priority_queue只有簡單的3個屬性獲取的函式, 其本身的操作也很簡單, 只是實現依賴了vectorheap就變得比較複雜.

class  priority_queue {
	...
public:
  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  const_reference top() const { return c.front(); }
    ...
};

push和pop實現

push和pop具體都是採用的heap演算法.

class  priority_queue {
	...
public:
  void push(const value_type& x) {
    __STL_TRY {
      c.push_back(x); 
        // 間接使用heap演算法
      push_heap(c.begin(), c.end(), comp);
    }
    __STL_UNWIND(c.clear());
  }
  void pop() {
    __STL_TRY {
     	// 間接使用heap演算法
      pop_heap(c.begin(), c.end(), comp);
      c.pop_back();
    }
    __STL_UNWIND(c.clear());
  }
};

實際操作

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	priority_queue<int> pq(a, a+4);
	while(!pq.empty())
	{
		cout << pq.top() << " ";	// 4, 3, 2, 1
		pq.pop();
	}

	exit(0);
}

總結

priority_queue本身實現是很複雜的, 但是當我們已經瞭解過vector, heap之後再來看, 他其實很簡單了, 就是將vector作為容器, heap作為演算法來操作的配置器, 這也體現了STL的靈活性是很高的, 通過各個容器與演算法的結合就能做出另一種功能的結構.