上一篇博客,带你深入理解STL之Deque容器中详细介绍了deque容器的源码实现方式。结合前面介绍的两个容器vector和list,在使用的过程中,我们确实要知道在什么情况下需要选择恰当的容器来满足需求和提升效率。一般选择的准则有如下几条:

  • 如果需要随机访问一个容器,vector比list要好
  • 如果需要经常插入和删除操作的话,list比vector要好
  • 如果既要随机存取,又要关心两端数据的插入和删除,则选择deque

好了,复习完前面的知识后,开始介绍今天的两个容器stack和queue。由于stack和queue都是基于deque来实现的,所以相应的代码会比较简单,也是比较轻松易实现的,下面一起去看看吧。

stack

如果把deque比作一个管道,两头都可进可出的话,stack就是一个桶!只能一头进一头出,而且,压在下面的东西你看不到,你要是想看,只能把上面的东西拿出来再去看。

stack是一种先进后出的数据结构,允许新增元素、移除元素和取得最顶端的元素,除了最顶端,没有任何其他方法可以存取stack中的元素,也就是说stack没有遍历行为,因此,stack是没有迭代器的!!!!!

以deque为底层容器来实现stack这种数据结构,简直不能再简单,基本的操作函数都已经定义好了,deque可以为它完成所有工作。与其说stack是一种容器,倒不如说它是一种配接器,一种容器适配器。

下面我们就来看看stack的源码,真的没骗你,超级简单。

template <class T, class Sequence = deque<T>  // 以deque作为缺省底层容器
class stack
{
    // #define __STL_NULL_TMPL_ARGS <>
  friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
  friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&);

public:
  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;   // 底层容器,stack全靠它来实现

public:
    // 以下函数直接调用底层容器的接口即可实现

  // 判断stack是否为空
  bool empty() const { return c.empty(); }  

  // stack中元素个数
  size_type size() const { return c.size(); }

  // 返回栈顶元素, 注意这里返回的是引用!!!
  reference top() { return c.back(); }
  const_reference top() const { return c.back(); }

  // 在栈顶追加新元素
  void push(const value_type& x) { c.push_back(x); }

  // 移除栈顶元素, 注意不返回元素的引用,
  // 很多初学者随机用此容器时经常误认为pop()操作同时会返回栈顶元素的引用
  void pop() { c.pop_back(); }
};

// 判断两个stack是否相等, 就要测试其内部维护容器是否相等
// x.c == y.c会调用容器重载的operator ==
template <class T, class Sequence>
bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y)
{
  return x.c == y.c;
}

// 比较两个迭代器的大小,即比较底层容器的大小
template <class T, class Sequence>
bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y)
{
  return x.c < y.c;
}

你没有看错,stack的源码就只有上面几句话,全是调用底层容器的接口。下面再来看看它的同胞queue,同样很简单。

queue

queue是一种先进先出的数据结构,上面说道,dequeu是个双向可进可出的管道,stack是一个桶,queue就是一个单向的水管,只能一端进,一端出。

queue允许新增元素、移除元素、从最底端插入元素,从最顶端取得元素,但是,从了最底端插入,最顶端取出之外,没有任何其他方法可以存取queue里面的元素,queue和stack一样,不允许有遍历行为,因此,queue也没有迭代器!!!!

queue和stack一样,也是一种容器适配器,只需要调用底层容器的接口就能实现。下面来看看它的源码吧。

template <class T, class Sequence = deque<T> >
class queue
{
  friend bool operator== __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
  friend bool operator< __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);

public:
  // 由于queue仅支持对队头和队尾的操作, 所以不定义STL要求的
  // pointer, iterator, difference_type
  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;   // 底层容器

public:
    // 以下操作和stack一样
  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(); }
};

// 重载==操作符,比较底层容器即可
template <class T, class Sequence>
bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y)
{
  return x.c == y.c;
}
// 同上
template <class T, class Sequence>
bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y)
{
  return x.c < y.c;
}

后记

这篇博客的两个”容器“比较容易理解,因为底层都已经学过了,只需要调用接口即可。最后再啰嗦两句,stack是一个先进后出的容器,queue是一个先进先出的容器,在使用过程中,需要根据你的需求来选择。我在刷leetcode的时候,碰到遍历二叉树的问题,基本上前、中后序遍历的非递归实现中,都会用到stack,而树的层序遍历中,会采用queue,具体的做法可以参考我的这片博文,全面剖析树的各类遍历方法,相信看完你会对stack和queue的使用有进一步的理解!

参考:

带你深入理解STL之Stack和Queue的更多相关文章

  1. 带你深入理解STL之Set和Map

    在上一篇博客带你深入理解STL之RBTree中,讲到了STL中关于红黑树的实现,理解起来比较复杂,正所谓前人种树,后人乘凉,RBTree把树都种好了,接下来就该set和map这类关联式容器来" ...

  2. 带你深入理解STL之Vector容器

    C++内置了数组的类型,在使用数组的时候,必须指定数组的长度,一旦配置了就不能改变了,通常我们的做法是:尽量配置一个大的空间,以免不够用,这样做的缺点是比较浪费空间,预估空间不当会引起很多不便. ST ...

  3. 带你深入理解STL之迭代器和Traits技法

    在开始讲迭代器之前,先列举几个例子,由浅入深的来理解一下为什么要设计迭代器. //对于int类的求和函数 int sum(int *a , int n) { int sum = 0 ; for (in ...

  4. 带你深入理解STL之RBTree

    最近一直忙于校招的笔试,STL的深入理解系列也耽搁了好几天,再加上!红黑树真的是超级超级难理解,超级超级复杂,参考了好多博客上的大神的理解才稍微明白一点,勉强入个门,下面请以一个菜鸟的角度跟着我一起学 ...

  5. 带你深入理解STL之Deque容器

    在介绍STL的deque的容器之前,我们先来总结一下vector和list的优缺点.vector在内存中是分配一段连续的内存空间进行存储,其迭代器采用原生指针即可,因此其支持随机访问和存储,支持下标操 ...

  6. 带你深入理解STL之List容器

    上一篇博客中介绍的vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,很好的支持了随机存取,但由于是连续空间,所以在中间进行插入.删除等操作时都造成了内存块的拷贝和移动,另外在内存空间 ...

  7. 带你深入理解STL之空间配置器(思维导图+源码)

    前不久把STL细看了一遍,由于看得太"认真",忘了做笔记,归纳和总结这步漏掉了.于是为了加深印象,打算重看一遍,并记录下来里面的一些实现细节.方便以后能较好的复习它. 以前在项目中 ...

  8. C++ STL:stack和queue

    http://blog.csdn.net/wallwind/article/details/6858634 http://blog.csdn.net/chao_xun/article/details/ ...

  9. [STL]deque和stack、queue

    怎么说呢,deque是一种双向开口的连续线性空间,至少逻辑上看上去是这样.然而事实上却没有那么简单,准确来说deque其实是一种分段连续空间,因此其实现以及各种操作比vector复杂的多. 一.deq ...

随机推荐

  1. 【bzoj4567 scoi2016】 背单词

    题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...

  2. 伸展树Splay【非指针版】

    ·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...

  3. 第三次C语言作业

    (一)改错题 计算f(x)的值:输入实数x,计算并输出下列分段函数f(x)的值,输出时保留1位小数. 输入输出样例1: Enterr x: 10.0 f(10.0) = 0.1 输入输出样例2: En ...

  4. windows server 2008 R2 NPS(网络连接策略服务)设置radius,实现telent登陆交换机路由器权限分配

    windows2008NPS(网络连接策略)设置radius 实现telent登陆交换机路由器权限分配 转载请说明出处 一,安装 首先在08中添加服务器角色网络策略和访问服务(Network Poli ...

  5. ubuntu14.04+sublime3+latex配置

    目的:用题目所说的三个东西写论文. 配置方法:参考 http://blog.csdn.net/bleedingfight/article/details/72810606, 但该博客所提的texliv ...

  6. Java基础学习(1)——反射

    反射就是把Java类中的各种成分映射成相应的Java类(主要用于框架开发) 反射的基石–>Class类 Java程序中的各个类属于同一事物,描述这类事务的Java类名就是Class. Class ...

  7. Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题

    Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...

  8. Go 语言教程

    Go 语言教程 Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易. Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发, ...

  9. CRM客户关系管理系统(七)

    第七章.动态modelform功能实现  7.1.动态modelform的实现 (1)给第一列添加一个a标签 kingadmintag.py (2)kingadmin/urls.py urlpatte ...

  10. Swift基础之如何使用iOS 9的Core Spotlight框架

    本文由CocoaChina译者KingOfOnePiece(博客)翻译 作者:GABRIEL THEODOROPOULOS?校对:hyhSuper 原文:How To Use Core Spotlig ...