SGI STL栈stack
stack简介
栈stack是一种先进后厨(FILO)的数据结构,只有一个出口,即栈顶。stack支持新增元素、移除元素、取得栈顶元素,但都是针对栈顶元素的操作,无法存取其他位置元素。
也就是说,stack不支持不影响栈结构的遍历操作。
将元素插入stack的操作称为push,将元素从stack移除(或弹出)的操作称为pop。
stack数据结构
SGISTL中,stack底层默认实现是依赖于deque(双端队列)。封闭deque的一端,只留一端进行新增元素、移除元素、查询元素的操作。
底层操作完全由其他容器实现,只是修改了deque的接口,称为adapter(适配器)。由于stack是以其他底部容器完成所有工作,因此往往不称为contain(容器),而称为container adapter(容器适配器)。
# define __STL_DEPENDENT_DEFAULT_TMPL(_Tp) = _Tp
// stack底层容器默认是deque
template <class _Tp,
class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(deque<_Tp>) >
class stack {
// __STD_QUALIFIER展开为std::, __STL_NULL_TMPL_ARGS展开为<>
friend bool __STD_QUALIFIER
operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
friend bool __STD_QUALIFIER
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 _Sequence container_type;
typedef typename _Sequence::reference reference;
typedef typename _Sequence::const_reference const_reference;
protected:
_Sequence c; // 底层容器
public:
stack() : c() {}
explicit stack(const _Sequence& __s) : c(__s) {}
// 以下利用Sequence c的操作, 完成stack的操作
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
reference top() { return c.back(); }
const_reference top() const { return c.back(); }
// deque是双端支持进出, stack只支持尾端进, 尾端出, 从而支持先进后出
void push(const value_type& __x) { c.push_back(__x); }
void pop() { c.pop_back(); }
};
// 比较两个stack x, y的所有元素是否相等
template <class _Tp, class _Seq>
bool operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
{
return __x.c == __y.c;
}
// 比较stack x是否小于stack y
template <class _Tp, class _Seq>
bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
{
return __x.c < __y.c;
}
stack没有迭代器
由于stack所有元素必须符合 “先进后出”的规则,只有栈顶元素才能被外部访问,因此不提供遍历功能,也不提供迭代器。
以list作为stack底层容器
除了deque,list也是双向开口的容器,也能作为stack的底层容器。stack要求底层容器支持empty(),size(),front(), back(),push_back(),pop_back()等接口。
以list作为stack底层容器示例:
int main()
{
stack<int, list<int>> istack;
istack.push(1);
istack.push(3);
istack.push(5);
istack.push(7);
cout << istack.size() << endl; // 4
cout << istack.top() << endl; // 7
istack.pop(); cout << istack.top() << endl; // 5
istack.pop(); cout << istack.top() << endl; // 3
istack.pop(); cout << istack.top() << endl; // 1
cout << istack.size() << endl; // 1
return 0;
}