带你深入理解STL之Stack和Queue
上一篇博客,带你深入理解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的源码剖析》
- C++ STL源码剖析
带你深入理解STL之Stack和Queue的更多相关文章
- 带你深入理解STL之Set和Map
在上一篇博客带你深入理解STL之RBTree中,讲到了STL中关于红黑树的实现,理解起来比较复杂,正所谓前人种树,后人乘凉,RBTree把树都种好了,接下来就该set和map这类关联式容器来" ...
- 带你深入理解STL之Vector容器
C++内置了数组的类型,在使用数组的时候,必须指定数组的长度,一旦配置了就不能改变了,通常我们的做法是:尽量配置一个大的空间,以免不够用,这样做的缺点是比较浪费空间,预估空间不当会引起很多不便. ST ...
- 带你深入理解STL之迭代器和Traits技法
在开始讲迭代器之前,先列举几个例子,由浅入深的来理解一下为什么要设计迭代器. //对于int类的求和函数 int sum(int *a , int n) { int sum = 0 ; for (in ...
- 带你深入理解STL之RBTree
最近一直忙于校招的笔试,STL的深入理解系列也耽搁了好几天,再加上!红黑树真的是超级超级难理解,超级超级复杂,参考了好多博客上的大神的理解才稍微明白一点,勉强入个门,下面请以一个菜鸟的角度跟着我一起学 ...
- 带你深入理解STL之Deque容器
在介绍STL的deque的容器之前,我们先来总结一下vector和list的优缺点.vector在内存中是分配一段连续的内存空间进行存储,其迭代器采用原生指针即可,因此其支持随机访问和存储,支持下标操 ...
- 带你深入理解STL之List容器
上一篇博客中介绍的vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,很好的支持了随机存取,但由于是连续空间,所以在中间进行插入.删除等操作时都造成了内存块的拷贝和移动,另外在内存空间 ...
- 带你深入理解STL之空间配置器(思维导图+源码)
前不久把STL细看了一遍,由于看得太"认真",忘了做笔记,归纳和总结这步漏掉了.于是为了加深印象,打算重看一遍,并记录下来里面的一些实现细节.方便以后能较好的复习它. 以前在项目中 ...
- C++ STL:stack和queue
http://blog.csdn.net/wallwind/article/details/6858634 http://blog.csdn.net/chao_xun/article/details/ ...
- [STL]deque和stack、queue
怎么说呢,deque是一种双向开口的连续线性空间,至少逻辑上看上去是这样.然而事实上却没有那么简单,准确来说deque其实是一种分段连续空间,因此其实现以及各种操作比vector复杂的多. 一.deq ...
随机推荐
- [HNOI2014]江南乐
Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一 ...
- noip2017"退役"记
day0 口胡了一下去年的六道题,感觉很稳,看了6集动漫,0点钟就去睡了. day1 早上被一阵革命练习曲吵醒,而我还是窝在被子里不想起床(-﹃-)~zZ.于是室友开始放起了lost river... ...
- 【PowerOJ1738】最小路径覆盖
Description 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个 顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶 ...
- 2015 多校联赛 ——HDU5400(水)
Sample Input 5 2 -2 0 2 0 -2 0 5 2 3 2 3 3 3 3 Sample Output 12 5 求最多多少序列满足,前半部分满足d(j+1) = d(j)+d1 ...
- 【Toll!Revisited(uva 10537)】
题目来源:蓝皮书P331 ·这道题使得我们更加深刻的去理解Dijkstra! 在做惯了if(dis[u]+w<dis[v])的普通最短路后,这道选择路径方案不是简单的比大小的题横在了 ...
- [Codeforces]871D Paths
失踪OJ回归. 毕竟这样的数论没做过几道,碰上一些具体的应用还是无所适从啊.小C还是借助这题大致摸索一下莫比乌斯函数吧. Description 有n个点,标号为1~n,为这n个点建一张无向图.两个点 ...
- 关于 Cannot forward after response has been committed的错误
这个错误顾名思义:就是在给客户端做出提交响应完毕后,就不能再次使用request的转发. 代码原先是这样的: package com.bdqn.jsp.study.web.filter; import ...
- C语言程序设计第三次作业 —— 选择结构(1)
(一)改错题 计算f(x)的值:输入实数x,计算并输出下列分段函数f(x)的值,输出时保留1位小数. (错误一) 错误原因及改正:第九行语句结尾缺少半角分号,添加分号即可改正 (错误二) 错误原因及改 ...
- C语言程序第二次作业
(一)改错题 1.输出带框文字:在屏幕上输出以下3行信息. ************* Welcome ************* 源程序 include int mian() { printf(&q ...
- 在浏览器中运行Keras模型,并支持GPU
Keras.js 推荐一下网页上的 demo https://transcranial.github.io/keras-js/#/ 加载的比较慢,但是识别的非常快. Run Keras models ...