C++ stack(STL stack)容器適配器用法詳解

stack 棧適配器是一種單端開口的容器(如圖 1 所示),實際上該容器模擬的就是棧存儲結構,即無論是向裏存數據還是從中取數據,都只能從這一個開口實現操作。

stack適配器示意圖
圖 1 stack 適配器示意圖

如圖 1 所示,stack 適配器的開頭端通常稱爲棧頂。由於數據的存和取只能從棧頂處進行操作,因此對於存取數據,stack 適配器有這樣的特性,即每次只能訪問適配器中位於最頂端的元素,也只有移除 stack 頂部的元素之後,才能訪問位於棧中的元素。

棧中存儲的元素滿足“後進先出(簡稱LIFO)”的準則,stack 適配器也同樣遵循這一準則。

stack容器適配器的創建

由於 stack 適配器以模板類 stack<T,Container=deque>(其中 T 爲存儲元素的類型,Container 表示底層容器的類型)的形式位於頭文件中,並定義在 std 命名空間裏。因此,在創建該容器之前,程序中應包含以下 2 行代碼:

#include <stack>
using namespace std;

std 命名空間也可以在使用 stack 適配器時額外註明。

創建 stack 適配器,大致分爲如下幾種方式。

  1. 創建一個不包含任何元素的 stack 適配器,並採用默認的 deque 基礎容器:
std::stack<int> values;

上面這行代碼,就成功創建了一個可存儲 int 類型元素,底層採用 deque 基礎容器的 stack 適配器。

  1. 上面提到,stack<T,Container=deque> 模板類提供了 2 個參數,通過指定第二個模板類型參數,我們可以使用出 deque 容器外的其它序列式容器,只要該容器支持 empty()、size()、back()、push_back()、pop_back() 這 5 個成員函數即可。

在介紹適配器時提到,序列式容器中同時包含這 5 個成員函數的,有 vector、deque 和 list 這 3 個容器。因此,stack 適配器的基礎容器可以是它們 3 箇中任何一個。例如,下面展示瞭如何定義一個使用 list 基礎容器的 stack 適配器:

std::stack<std::string, std::list<int>> values;
  1. 可以用一個基礎容器來初始化 stack 適配器,只要該容器的類型和 stack 底層使用的基礎容器類型相同即可。例如:
std::list<int> values {1, 2, 3};
std::stack<int,std::list<int>> my_stack (values);

注意,初始化後的 my_stack 適配器中,棧頂元素爲 3,而不是 1。另外在第 2 行代碼中,stack 第 2 個模板參數必須顯式指定爲 list(必須爲 int 類型,和存儲類型保持一致),否則 stack 底層將默認使用 deque 容器,也就無法用 lsit 容器的內容來初始化 stack 適配器。

  1. 還可以用一個 stack 適配器來初始化另一個 stack 適配器,只要它們存儲的元素類型以及底層採用的基礎容器類型相同即可。例如:
std::list<int> values{ 1, 2, 3 };
std::stack<int, std::list<int>> my_stack1(values);
std::stack<int, std::list<int>> my_stack=my_stack1;
//std::stack<int, std::list<int>> my_stack(my_stack1);

可以看到,和使用基礎容器不同,使用 stack 適配器給另一個 stack 進行初始化時,有 2 種方式,使用哪一種都可以。

注意,第 3、4 種初始化方法中,my_stack 適配器的數據是經過拷貝得來的,也就是說,操作 my_stack 適配器,並不會對 values 容器以及 my_stack1 適配器有任何影響;反過來也是如此。

stack容器適配器支持的成員函數

和其他序列容器相比,stack 是一類存儲機制簡單、提供成員函數較少的容器。表 1 列出了 stack 容器支持的全部成員函數。

成員函數 功能
empty() 當 stack 棧中沒有元素時,該成員函數返回 true;反之,返回 false。
size() 返回 stack 棧中存儲元素的個數。
top() 返回一個棧頂元素的引用,類型爲 T&。如果棧爲空,程序會報錯。
push(const T& val) 先複製 val,再將 val 副本壓入棧頂。這是通過調用底層容器的 push_back() 函數完成的。
push(T&& obj) 以移動元素的方式將其壓入棧頂。這是通過調用底層容器的有右值引用參數的 push_back() 函數完成的。
pop() 彈出棧頂元素。
emplace(arg…) arg… 可以是一個參數,也可以是多個參數,但它們都只用於構造一個對象,並在棧頂直接生成該對象,作爲新的棧頂元素。
swap(stack & other_stack) 將兩個 stack 適配器中的元素進行互換,需要注意的是,進行互換的 2 個 stack 適配器中存儲的元素類型以及底層採用的基礎容器類型,都必須相同。

下面這個例子中演示了表 1 中部分成員函數的用法:

#include <iostream>
#include <stack>
#include <list>
using namespace std;
int main()
{
    //構建 stack 容器適配器
    list<int> values{ 1, 2, 3 };
    stack<int, list<int>> my_stack(values);
    //查看 my_stack 存儲元素的個數
    cout << "size of my_stack: " << my_stack.size() << endl;
    //將 my_stack 中存儲的元素依次彈棧,直到其爲空
    while (!my_stack.empty())
    {  
        cout << my_stack.top() << endl;
        //將棧頂元素彈棧
        my_stack.pop();
    }
    return 0;
}

運行結果爲:

size of my_stack: 3
3
2
1

表 1 中其它成員函數的用法也非常簡單,這裏不再給出具體示例,後續章節用法會做具體介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章