1. 程式人生 > >10、【C++ STL】容器適配器(stack queue priority_queue)

10、【C++ STL】容器適配器(stack queue priority_queue)

pub function 適配 pty str 成員 cto ali The

容器適配器

  stack、queue、priority_queue 都不支持任一種叠代器,它們都是容器適配器類型,stack是用vector/deque/list對象創建了一個先進後出容器;queue是用deque或list對象創建了一個先進先出容器;priority_queue是用vector/deque創建了一個排序隊列,內部用二叉堆實現。

1、stack

stack的源碼如下:

 1 // TEMPLATE CLASS stack
 2 template < class _Ty,
 3          class _Container = deque<_Ty> >
 4
class stack 5 { 6 // LIFO queue implemented with a container 7 public: 8 typedef _Container container_type; 9 typedef typename _Container::value_type value_type; 10 typedef typename _Container::size_type size_type; 11 typedef typename _Container::reference reference; 12 typedef typename _Container::const_reference const_reference;
13 14 stack() 15 : c() 16 { 17 // construct with empty container 18 } 19 20 explicit stack(const _Container &_Cont) 21 : c(_Cont) 22 { 23 // construct by copying specified container 24 } 25 26 bool empty() const 27 { 28 // test if stack is empty
29 return (c.empty()); 30 } 31 32 size_type size() const 33 { 34 // test length of stack 35 return (c.size()); 36 } 37 38 reference top() 39 { 40 // return last element of mutable stack 41 return (c.back()); 42 } 43 44 const_reference top() const 45 { 46 // return last element of nonmutable stack 47 return (c.back()); 48 } 49 50 void push(const value_type &_Val) 51 { 52 // insert element at end 53 c.push_back(_Val); 54 } 55 56 void pop() 57 { 58 // erase last element 59 c.pop_back(); 60 } 61 62 const _Container &_Get_container() const 63 { 64 // get reference to container 65 return (c); 66 } 67 68 protected: 69 _Container c; // the underlying container 70 };

  即有一個_Container 成員,默認是deque<_Ty> ,當然也可以傳遞vector, list 進去,只要支持push_back,pop_back 等接口。

【stack示例】

 1 #include <iostream>
 2 #include <vector>
 3 #include <list>
 4 #include <stack>
 5 
 6 using namespace std;
 7 
 8 int main(void)
 9 {
10     stack< int, list<int> > s;
11     //add elements
12     for(int i = 0; i < 5; i++)
13     {
14         s.push(i);
15     }
16     //print all elements
17     while(!s.empty())
18     {
19         cout << s.top() << " ";
20         s.pop();
21     }
22     cout << endl;
23 
24     return 0;
25 }

2、queue

queue的源碼:

 1 // TEMPLATE CLASS queue
 2 template < class _Ty,
 3          class _Container = deque<_Ty> >
 4 class queue
 5 {
 6     // FIFO queue implemented with a container
 7 public:
 8     typedef _Container container_type;
 9     typedef typename _Container::value_type value_type;
10     typedef typename _Container::size_type size_type;
11     typedef typename _Container::reference reference;
12     typedef typename _Container::const_reference const_reference;
13 
14     queue()
15         : c()
16     {
17         // construct with empty container
18     }
19 
20     explicit queue(const _Container &_Cont)
21         : c(_Cont)
22     {
23         // construct by copying specified container
24     }
25 
26     bool empty() const
27     {
28         // test if queue is empty
29         return (c.empty());
30     }
31 
32     size_type size() const
33     {
34         // return length of queue
35         return (c.size());
36     }
37 
38     reference front()
39     {
40         // return first element of mutable queue
41         return (c.front());
42     }
43 
44     const_reference front() const
45     {
46         // return first element of nonmutable queue
47         return (c.front());
48     }
49 
50     reference back()
51     {
52         // return last element of mutable queue
53         return (c.back());
54     }
55 
56     const_reference back() const
57     {
58         // return last element of nonmutable queue
59         return (c.back());
60     }
61 
62     void push(const value_type &_Val)
63     {
64         // insert element at beginning
65         c.push_back(_Val);
66     }
67 
68     void pop()
69     {
70         // erase element at end
71         c.pop_front();
72     }
73 
74     const _Container &_Get_container() const
75     {
76         // get reference to container
77         return (c);
78     }
79 
80 protected:
81     _Container c;   // the underlying container
82 };

  實現跟stack 是很類似的,只是queue不能用vector 實現,因為沒有pop_front 接口。

【queue示例】

 1 #include <iostream>
 2 #include <vector>
 3 #include <list>
 4 #include <stack>
 5 #include <queue>
 6 
 7 using namespace std;
 8 
 9 int main(void)
10 {
11     queue< int, list<int> > q;
12     //add elements
13     for(int i = 0; i < 5; i++)
14     {
15         q.push(i);
16     }
17     //print all elements
18     while(!q.empty())
19     {
20         cout << q.front() << " ";
21         q.pop();
22     }
23     cout << endl;
24 
25     return 0;
26 }

3、priority_queue

priority_queue的源碼:

  1 // TEMPLATE CLASS priority_queue
  2 template < class _Ty,
  3          class _Container = vector<_Ty>,
  4          class _Pr = less<typename _Container::value_type> >
  5 class priority_queue
  6 {
  7     // priority queue implemented with a _Container
  8 public:
  9     typedef _Container container_type;
 10     typedef typename _Container::value_type value_type;
 11     typedef typename _Container::size_type size_type;
 12     typedef typename _Container::reference reference;
 13     typedef typename _Container::const_reference const_reference;
 14 
 15     priority_queue()
 16         : c(), comp()
 17     {
 18         // construct with empty container, default comparator
 19     }
 20 
 21     explicit priority_queue(const _Pr &_Pred)
 22         : c(), comp(_Pred)
 23     {
 24         // construct with empty container, specified comparator
 25     }
 26 
 27     priority_queue(const _Pr &_Pred, const _Container &_Cont)
 28         : c(_Cont), comp(_Pred)
 29     {
 30         // construct by copying specified container, comparator
 31         make_heap(c.begin(), c.end(), comp);
 32     }
 33 
 34     template<class _Iter>
 35     priority_queue(_Iter _First, _Iter _Last)
 36         : c(_First, _Last), comp()
 37     {
 38         // construct by copying [_First, _Last), default comparator
 39         make_heap(c.begin(), c.end(), comp);
 40     }
 41 
 42     template<class _Iter>
 43     priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred)
 44         : c(_First, _Last), comp(_Pred)
 45     {
 46         // construct by copying [_First, _Last), specified comparator
 47         make_heap(c.begin(), c.end(), comp);
 48     }
 49 
 50     template<class _Iter>
 51     priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred,
 52                    const _Container &_Cont)
 53         : c(_Cont), comp(_Pred)
 54     {
 55         // construct by copying [_First, _Last), container, and comparator
 56         c.insert(c.end(), _First, _Last);
 57         make_heap(c.begin(), c.end(), comp);
 58     }
 59 
 60     bool empty() const
 61     {
 62         // test if queue is empty
 63         return (c.empty());
 64     }
 65 
 66     size_type size() const
 67     {
 68         // return length of queue
 69         return (c.size());
 70     }
 71 
 72     const_reference top() const
 73     {
 74         // return highest-priority element
 75         return (c.front());
 76     }
 77 
 78     reference top()
 79     {
 80         // return mutable highest-priority element (retained)
 81         return (c.front());
 82     }
 83 
 84     void push(const value_type &_Pred)
 85     {
 86         // insert value in priority order
 87         c.push_back(_Pred);
 88         push_heap(c.begin(), c.end(), comp);
 89     }
 90 
 91     void pop()
 92     {
 93         // erase highest-priority element
 94         pop_heap(c.begin(), c.end(), comp);
 95         c.pop_back();
 96     }
 97 
 98 protected:
 99     _Container c;   // the underlying container
100     _Pr comp;   // the comparator functor
101 };

  priority_queue 的實現稍微復雜一點,可以傳遞3個參數,而且有兩個成員,comp 即自定義比較邏輯,默認是less<value_type>,在構造函數中調用make_heap函數構造二叉堆,comp 主要是用於構造二叉堆時的判別,如果是less 則構造大堆,如果傳遞greater 則構造小堆.
  註意,priority_queue 不能用list 實現,因為list 只支持雙向叠代器,而不支持隨機叠代器。
【priority_queue示例】

 1 #include <iostream>
 2 #include <functional>
 3 #include <vector>
 4 #include <list>
 5 #include <stack>
 6 #include <queue>
 7 
 8 using namespace std;
 9 
10 int main(void)
11 {
12     int a[] = {5, 1, 2, 4, 3};
13     //creat priority_queue and initialize priority_queue
14     //less<int>構造大堆
15     //greater<int>構造小堆
16     priority_queue < int, vector<int>, less<int> > q(a, a+5);
17 
18     //print all elements
19     while(!q.empty())
20     {
21         cout << q.top() << " ";
22         q.pop();
23     }
24     cout << endl;
25 
26     return 0;
27 }

下面舉個例子說明make_heap 函數的用法:

 1 #include <iostream>
 2 #include <functional>
 3 #include <algorithm>//sort()
 4 #include <iterator>//ostream_iterator
 5 #include <vector>
 6 #include <list>
 7 #include <stack>
 8 #include <queue>
 9 
10 using namespace std;
11 
12 int main(void)
13 {
14     int a[] = {5, 1, 2, 4, 3};
15     make_heap(a, a+5, less<int>());
16 
17     //copy函數會將a,a+5區間的內的值拷貝至ostream_iterator中
18     //ostream_iterator< int >(cout, " ")是一個函數對象,其功能是依次打印ostream_iterator中的
19     //值,並以空格分割
20     copy(a, a+5, ostream_iterator< int >(cout, " "));
21     cout << endl;
22 
23     sort(a, a+5);
24 
25     //copy函數會將a,a+5區間的內的值拷貝至ostream_iterator中
26     copy(a, a+5, ostream_iterator< int >(cout, " "));
27     cout << endl;
28 
29     return 0;
30 }

執行結果:

1   5 4 2 1 3
2   1 2 3 4 5

  make_heap() 將容器的元素構造成二叉堆,傳遞的是less,即構造的是大堆,把大堆層序遍歷的結果存入數組,再調用sort() 進行排序,內部調用的實際算法不一定,可以是堆排序、插入排序、選擇排序等等,跟蹤進去發現調用的是插入排序;當然也可以直接指定使用堆排序 sort_heap(調用者必須已經是堆了,也就是前面已經先調用了make_heap,而且大小堆類型得匹配),與make_heap 一樣,第三個參數傳遞的都是函數對象的用法。sort 和 sort_heap 默認都是從小到大排序,除非重載的版本傳遞了第三個參數,如下,第三個參數可以是函數指針,也可以是函數對象:

1 // order heap by repeatedly popping, using operator<
2 template<class _RanIt> inline
3 void sort_heap(_RanIt _First, _RanIt _Last);
4 
5 // order heap by repeatedly popping, using _Pred
6 template < class _RanIt,
7          class _Pr > inline
8 void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred);

10、【C++ STL】容器適配器(stack queue priority_queue)