1. 程式人生 > >SGISTL原始碼閱讀十七 stack(棧)

SGISTL原始碼閱讀十七 stack(棧)

SGISTL原始碼閱讀十七 stack(棧)

前言

前面我們已經學習了序列式容器vectorlistdeque
本次要進行分析的是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的資料結構,我們將在下一篇文章中分析它。