stl标准库系列之--queue


我们在前面说stack的时候已经说过了什么叫容器适配器,如果有不了解的,可以去前面 看一看

这里呢,我们主要讲下queue,作为生活里面我们司空见惯了的现像,应该是不叫好理解的。

1、queue容器的定义

和 stack 栈容器适配器不同,queue 是一种先进先出(FIFO)的数据结构,queue 容器适配器有 2 个开口,其中一个开口专门用来输入数据,另一个专门用来输出数据。但是queue元素的加入和取出是固定的,比如加入只能在队尾加入,取出只能在队前,其他地方都不能进行元素的操作。简单的说,queue不能进行遍历。

我们先开一下queue的示意图:
在这里插入图片描述

由上面的示意图我们可以看出,queue的访问只能访问到队前和队尾的两个元素,不能逾越它的规则,访问对中间的元素。

下面我们看下SGI源码中对queue的定义:

template <class _Tp, class _Sequence>
class queue {

  // requirements:

  __STL_CLASS_REQUIRES(_Tp, _Assignable);
  __STL_CLASS_REQUIRES(_Sequence, _FrontInsertionSequence);
  __STL_CLASS_REQUIRES(_Sequence, _BackInsertionSequence);
  typedef typename _Sequence::value_type _Sequence_value_type;
  __STL_CLASS_REQUIRES_SAME_TYPE(_Tp, _Sequence_value_type);


#ifdef __STL_MEMBER_TEMPLATES 
  template <class _Tp1, class _Seq1>
  friend bool operator== (const queue<_Tp1, _Seq1>&,
                          const queue<_Tp1, _Seq1>&);
  template <class _Tp1, class _Seq1>
  friend bool operator< (const queue<_Tp1, _Seq1>&,
                         const queue<_Tp1, _Seq1>&);
#else /* __STL_MEMBER_TEMPLATES */
  friend bool __STD_QUALIFIER
  operator== __STL_NULL_TMPL_ARGS (const queue&, const queue&);
  friend bool __STD_QUALIFIER
  operator<  __STL_NULL_TMPL_ARGS (const queue&, const queue&);
#endif /* __STL_MEMBER_TEMPLATES */

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;
public:
  queue() : c() {}
  explicit queue(const _Sequence& __c) : c(__c) {}

  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  reference front() { return c.front(); }
  const_reference front() const { return c.front(); }
  reference back() { return c.back(); }
  const_reference back() const { return c.back(); }
  void push(const value_type& __x) { c.push_back(__x); }
  void pop() { c.pop_front(); }
};

其实,我们也能够很明显的发现,我们对queue的操作,都是直接调用了它的底层序列容器的方法,这一点上和stack是一致的。

2、queue容器的创建

#include <queue>
using namespace std;

1、创建一个不包含任何元素的 queue 适配器,并采用默认的 deque 基础容器

std::queue<int> data;

2、创建指定底层容器的 stack 适配器

std::queue<int, std::list<int>> data; //以list为底层容器,创建一个空的queue

std::list<int> values {5, 6, 7, 8};
std::queue<int, std::list<int>> data(values);

我们通过上一节的学习也能够看出来,其实queue的底层容器是没有stack那么多的,只有list是支持的。

3、基础容器来初始化

//跟默认的基本上是一样的,这边需要注意的是,deque的元素类型必须和queue的保持一致
std::deque<int> data {1, 2, 3};
std::queue<int> data1(data);

4、赋值

std::deque<int> data{1, 2, 3};
std::queue<int> data1(data);
    
std::queue<int> data2 = data1;

通过这种赋值的方法来创建新的queue适配器,是不会影响第一个适配器的,也就是是不会影响data1的。

3、迭代器

前面我们已经说过了,queue只能访问队前和队尾的两个元素,那也就意味着queue是不能被遍历的,也就是说,queue是没有迭代器的。

4、成员函数

成员函数函数说明
empty()判断queue是否为空,为空返回true,否则返回false
size()返回queue中的元素的实际个数
(const) front()返回queue队列第一个元素的引用(const),栈为空则返回未定义元素
(const) back()返回queue队列最后一个元素的引用(const),栈为空则返回未定义元素
push(const T& val)调用底层的push_back函数,先复制,再插入副本
push(T&& obj)移动元素的方式在queue队尾添加元素,底层容器支持
pop()移除queue第一个元素
emplace(arg…)在队尾插入元素
swap(queue & other_queue)将两个 queue适配器中的元素进行互换,两个队列的基础容器、元素类型必须相同

5、使用

queue的使用,我们参考了下stack的运用,比较简单。


#include <iostream>
#include <queue>
#include <list>

using namespace std;

template<class T>
void display(T& data)   //注意函数的入参,会修改传入的变量
{
//    int nCount = data.size();
//    for(int nIndex = 0; nIndex < nCount; ++nIndex)  //如果使用for循环遍历,则不能用data.size()直接代替nCount,因为data.front()会改变data.size()
    while (!data.empty())
    {
        cout << data.front() << " ";
        data.pop();
    }
    cout << endl;
}

int main(int argc, char* argv[])
{
    queue<int> data0;
    for(int nIndex = 0; nIndex < 10; ++nIndex)
    {
        data0.push(nIndex);
    }
    display(data0);     // 0 1 2 3 4 5 6 7 8 9

    queue<int, list<int>> data;
    for(int nIndex = 1; nIndex <= 10; ++nIndex)
    {
        data.push(nIndex * 2);
    }
    display(data);     // 2 4 6 8 10 12 14 16 18 20

    list<int> values {5, 6, 7, 8};
    queue<int, list<int>> data1(values);
    display(data1);     // 8 7 6 5

    list<int> value {11, 12, 13, 14};
    queue<int, list<int>> data2(value);
    queue<int, list<int>> data3 = data2;
    display(data3);     // 11 12 13 14
    display(data2);     // 11 12 13 14
    return 0;
}

结果如下:
在这里插入图片描述
其实,容器有很多,重要的是我们需要能够在面对实际场景时,能够准确的选择容器。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值