STL源码剖析——序列式容器#4 Stack & Queue
Stack
stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口,元素的新增、删除、最顶端访问都在该出口进行,没有其他位置和方法可以存取stack的元素。换言之,stack不允许有遍历行为。
在学习了deque之后,我们知道了deque是一个双向开口的结构,deque的首尾端都能进行元素的插入和删除。我们既然拥有了这样的一个结构,那只要稍加调整就能符合stack的特征了,不必再另起炉灶。若以deque为底部机构并封闭其前端开口,保留尾端开口,便轻而易举地形成了一个stack。因此,SGI STL便以deque作为缺省情况下的stack底部结构,stack的实现因而非常简单,源码十分简短。
1 #ifndef __STL_LIMITED_DEFAULT_TEMPLATES 2 template <class T, class Sequence = deque<T> > 3 #else 4 template <class T, class Sequence> 5 #endif 6 class stack { 7 //以下 __STL_NULL_TMPL_ARGS会展开为<>,是来自别处的typedef 8 friend bool operator== __STL_NULL_TMPL_ARGS(const stack&, const stack&); 9 friend bool operator< __STL_NULL_TMPL_ARGS(const stack&, const stack&); 10 public: 11 //与deque别无二致的相应类型 12 typedef typename Sequence::value_type value_type; 13 typedef typename Sequence::size_type size_type; 14 typedef typename Sequence::reference reference; 15 typedef typename Sequence::const_reference const_reference; 16 protected: 17 Sequence c; // 底层容器,缺省为deque<T> 18 public: 19 // 以下完全利用 Sequence c 的操作,完成 stack 的操作。 20 bool empty() const { return c.empty(); } 21 size_type size() const { return c.size(); } 22 reference top() { return c.back(); } 23 const_reference top() const { return c.back(); } 24 // deque 是两头可进出,stack 是末端进,末端出(所以后进者先出)。 25 void push(const value_type& x) { c.push_back(x); } 26 void pop() { c.pop_back(); } 27 }; 28 29 template <class T, class Sequence> 30 bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) { 31 return x.c == y.c; 32 } 33 34 template <class T, class Sequence> 35 bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y) { 36 return x.c < y.c; 37 } 38 39 __STL_END_NAMESPACE 40 41 #endif /* __SGI_STL_INTERNAL_STACK_H */
另注,stack没有迭代器,因为stack的所有元素必须符合“先进后出”的条件,只有stack最顶端的元素,才有被机会访问或弹出。所以stack不提供遍历功能,也不提供迭代器。
Queue
与之相反,有先进后出的数据结构,肯定也会有先进先出的数据结构,queue就是一种先进先出的数据结构。它有一个入口、一个出口,允许从最底端加入元素,从最顶端弹出元素,除了这两个存取操作外,没有任何其他方法可以存取queue的其他元素。同样,它不允许有遍历行为。
我们只要取deque的部分功能便可实现queue的全部。所以queue的实现非常简单,源码十分简短:
1 #ifndef __STL_LIMITED_DEFAULT_TEMPLATES 2 template <class T, class Sequence = deque<T> > 3 #else 4 template <class T, class Sequence> 5 #endif 6 class queue { 7 friend bool operator== __STL_NULL_TMPL_ARGS(const queue& x, const queue& y); 8 friend bool operator< __STL_NULL_TMPL_ARGS(const queue& x, const queue& y); 9 public: 10 typedef typename Sequence::value_type value_type; 11 typedef typename Sequence::size_type size_type; 12 typedef typename Sequence::reference reference; 13 typedef typename Sequence::const_reference const_reference; 14 protected: 15 Sequence c; // 底层容器 16 public: 17 // 以下完全利用 Sequence c 的操作,完成 queue 的操作。 18 bool empty() const { return c.empty(); } 19 size_type size() const { return c.size(); } 20 reference front() { return c.front(); } 21 const_reference front() const { return c.front(); } 22 reference back() { return c.back(); } 23 const_reference back() const { return c.back(); } 24 // deque 是两头可进出,queue 是末端进,前端出(所以先进先出)。 25 void push(const value_type& x) { c.push_back(x); } 26 void pop() { c.pop_front(); } 27 }; 28 template <class T, class Sequence> 29 bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y) 30 { 31 return x.c == y.c; 32 } 33 template <class T, class Sequence> 34 bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y) 35 { 36 return x.c < y.c; 37 }
同样,queue不提供迭代器。