SGISTL源码阅读十七 stack(栈)
前言
前面我们已经学习了序列式容器vector
,list
和deque
。
本次要进行分析的是stack
,它是一种先进后出(First In Lat Out,FILO)数据结构,在学习数据结构的时候应该都接触过,在这里stack
是一个配接器(adapter),它默认以deque
容器作为它的底部结构实现。接下来我们深入源码进行学习。
- 配接器
具有这种“修改某物接口,形成另一种风貌”之性质者,称为adapter
深入源码
stack
的定义部分
#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
//使用了deque作为它的底层
template <class T, class Sequence = deque<T> >
#else
//也可指定
template <class T, class Sequence>
#endif
class stack {
//操作符重载,友元函数声明
friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&);
public:
//声明了相应型别
//但是我们可以注意到这里只有4个,stack是没有迭代器的
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:
//默认使用了deque作为底层容器
Sequence c;
通过以上源码我们发现stack
并没有迭代器,但是这一点并不难理解。所有进入stack
的元素都必须满足FILO,它并不提供遍历或是其他访问操作,只能从stack
的顶端pop
出元素或者通过top
获取顶部的元素。
stack
操作符重载
//重载==
template <class T, class Sequence>
bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
//底层的Sequence相等则两个stack相等
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
提供的接口
stack
所提供的接口也是完全利用了底层容器c来完成操作
public:
//判断stack是否为空
bool empty() const { return c.empty(); }
//获取stack的长度
size_type size() const { return c.size(); }
//获取stack的顶部元素
reference top() { return c.back(); }
const_reference top() const { return c.back(); }
//将元素压栈
void push(const value_type& x) { c.push_back(x); }
//将元素从顶部弹出
void pop() { c.pop_back(); }
stack
的简单使用
从源码可以看出,stack
缺省使用deque
作为它的底层容器,但是也可以指定底层容器。
#include <iostream>
#include <stack>
using namespace std;
int main()
{
//缺省使用deque作为底层容器
stack<int> mystack;
mystack.push(6);
mystack.push(2);
mystack.push(5);
mystack.push(0);
cout << "size:" << mystack.size() << endl;
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "size:" << mystack.size() << endl;
return 0;
}
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main()
{
//stack<int> mystack;
//指定vector作为底层容器
stack<int, vector<int> > mystack;
mystack.push(6);
mystack.push(2);
mystack.push(5);
mystack.push(0);
cout << "size:" << mystack.size() << endl;
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "top element:" << mystack.top() << endl;
mystack.pop();
cout << "size:" << mystack.size() << endl;
return 0;
}
总结
在阅读STL源码之前对stack
可能的数据结构已经比较清楚了,因为它是最最基础的一个数据结构了。之前也自己实现过stack
,底层无非使用到了数组和链表。
阅读了STL源码发现它只是一个配接器,通过调用比它更加底层的容器来进行操作,代码也非常地简单。
我们常把另外一个数据结构和stack
作比较,那就是queue
,一种FIFO的数据结构,我们将在下一篇文章中分析它。