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


    容器适配器

      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);
  • 相关阅读:
    机器学习第二章复习
    机器学习第三章复习
    机器学习第四章复习
    第一次作业
    第二次作业
    第06组 Beta版本演示
    第06组 Beta冲刺(4/4)
    第06组 Beta冲刺(3/4)
    第06组 Beta冲刺(2/4)
    第06组 Beta冲刺(1/4)
  • 原文地址:https://www.cnblogs.com/Long-w/p/9831351.html
Copyright © 2020-2023  润新知