深入解析C++ STL Stack:后進先出的數據結構

一、引言

在計算機科學中,棧(Stack)作為一種遵循后進先出(LIFO)?原則的數據結構,是算法設計和程序開發的基礎構件。C++ STL中的stack容器適配器以簡潔的接口封裝了底層容器的操作,為開發者提供了高效的LIFO操作方案。本文將通過完整代碼示例,深入剖析stack的核心機制,揭示其底層實現原理,并探討最佳實踐與常見陷阱。文章包含4000余字詳細解析,幫助開發者全面掌握棧的應用藝術。

https://example.com/stack-structure.png

二、環境準備

  • ?編譯器要求?:支持C++11及以上標準
  • ?開發環境?:Visual Studio/CLion/Code::Blocks
  • ?關鍵頭文件?:#include <stack>
  • ?命名空間?:using namespace std;

三、完整代碼示例

cpp

#include <iostream>
#include <stack>
using namespace std;int main() {// 創建一個整數類型的棧stack<int> myStack;// 壓入元素到棧中myStack.push(10);myStack.push(20);myStack.push(30);// 訪問棧頂元素cout << "棧頂元素: " << myStack.top() << endl; // 輸出: 30// 彈出棧頂元素myStack.pop();cout << "彈出后棧頂元素: " << myStack.top() << endl; // 輸出: 20// 檢查棧是否為空if (myStack.empty()) {cout << "棧為空" << endl;}else {cout << "棧不為空" << endl;}// 獲取棧的大小cout << "棧的大小: " << myStack.size() << endl; // 輸出: 2// 遍歷棧(棧沒有直接遍歷的方法,需要依次彈出元素)cout << "棧中的元素: ";while (!myStack.empty()) {cout << myStack.top() << " "; // 輸出棧頂元素myStack.pop(); // 彈出棧頂元素}cout << endl;// 再次檢查棧是否為空if (myStack.empty()) {cout << "棧為空" << endl; // 輸出: 棧為空}return 0;
}

四、核心操作解析

4.1 容器初始化

cpp

stack<int> myStack;  // 創建空棧(默認使用deque作為底層容器)
stack<int, vector<int>> vecStack;  // 使用vector作為底層容器

?關鍵特性?:

  • 默認底層容器為deque,但支持自定義(vector/list)
  • 初始化時自動構造空容器,無默認容量限制

4.2 基本操作指令

操作時間復雜度行為描述示例
push(x)O(1)將元素x壓入棧頂myStack.push(100);
pop()O(1)移除棧頂元素(不返回元素值)myStack.pop();
top()O(1)訪問棧頂元素int x = myStack.top();
empty()O(1)檢查棧是否為空if(myStack.empty())
size()O(1)返回棧中元素數量int s = myStack.size();

?底層實現原理?:

cpp

// 典型stack實現(以deque為底層容器)
template<typename T, typename Container=deque<T>>
class stack {
protected:Container c;  // 底層容器
public:void push(const T& val) { c.push_back(val); }void pop() { c.pop_back(); }T& top() { return c.back(); }// ...其他成員函數
};

五、進階操作實踐

5.1 自定義底層容器

cpp

// 使用vector作為底層容器
stack<int, vector<int>> vecStack;
vecStack.push(10);  // 底層調用vector::push_back// 使用list作為底層容器
stack<int, list<int>> listStack;
listStack.push(20); // 底層調用list::push_back

?性能對比?:

底層容器push操作pop操作內存連續性適用場景
dequeO(1)O(1)通用場景(默認選擇)
vectorO(1)O(1)預知最大容量
listO(1)O(1)頻繁中間插入刪除

5.2 棧的容量管理

cpp

stack<int> s;
cout << "當前容量: " << s.size() << endl;  // 輸出0s.push(1);
cout << "容量變化: " << s.size() << endl;  // 輸出1// 注意:標準庫stack不提供capacity()方法
// 需要通過size()跟蹤元素數量

六、遍歷操作的深度探討

6.1 間接遍歷方法

cpp

stack<int> tempStack = originalStack;
while (!tempStack.empty()) {process(tempStack.top());tempStack.pop();
}

?注意事項?:

  • 遍歷會破壞原有棧結構
  • 需要臨時副本保留原始數據

6.2 迭代器模擬實現

cpp

// 自定義棧迭代器(僅用于演示原理)
template<typename T>
class StackIterator {typename deque<T>::reverse_iterator rit;
public:StackIterator(typename deque<T>::reverse_iterator it) : rit(it) {}T& operator*() { return *rit; }StackIterator& operator++() { ++rit; return *this; }bool operator!=(const StackIterator& other) { return rit != other.rit; }
};// 使用示例
stack<int> s;
s.push(1); s.push(2); s.push(3);
auto begin = StackIterator<int>(s.c.rbegin());
auto end = StackIterator<int>(s.c.rend());
for (auto it = begin; it != end; ++it) {cout << *it << " ";  // 輸出1 2 3
}

七、性能優化策略

7.1 預分配內存(vector底層容器)

cpp

vector<int> vec;
vec.reserve(1000);  // 預分配內存
stack<int, vector<int>> s(vec);  // 使用預分配空間// 測試性能
for (int i=0; i<100000; ++i) {s.push(i);  // 減少動態擴容次數
}

7.2 移動語義優化

cpp

stack<vector<int>> s;
vector<int> bigData(1000000, 42);// 使用移動語義避免深拷貝
s.push(move(bigData));  // bigData變為空

八、常見陷阱與解決方案

8.1 迭代器失效問題

cpp

stack<int> s;
s.push(1); s.push(2);
auto it = s.c.rbegin();  // 獲取反向迭代器
s.pop();                 // 導致迭代器失效
cout << *it;             // 未定義行為!

?解決方案?:

  • 操作前復制棧內容
  • 使用索引訪問(僅適用于vector底層)

8.2 多線程安全問題

cpp

// 非線程安全操作
void unsafe_push(stack<int>& s) {for (int i=0; i<1000; ++i) {s.push(i);  // 可能出現數據競爭}
}// 解決方案:使用互斥鎖
mutex mtx;
void safe_push(stack<int>& s) {lock_guard<mutex> lock(mtx);for (int i=0; i<1000; ++i) {s.push(i);}
}

九、與其他容器的對比

特性stackqueuepriority_queue
訪問原則LIFOFIFO最大/最小元素優先
底層容器默認dequedequevector
典型應用場景函數調用任務隊列拓撲排序
時間復雜度(插入)O(1)O(1)O(log n)

十、實戰應用場景

10.1 函數調用棧模擬

cpp

// 模擬函數調用過程
stack<pair<string, int>> callStack;
callStack.push({"main", 0x1000});
callStack.push({"foo", 0x2000});
cout << "當前執行函數: " << callStack.top().first << endl;  // 輸出foo
callStack.pop();

10.2 括號匹配驗證

cpp

bool validateParentheses(string s) {stack<char> st;for (char c : s) {if (c == '(' || c == '[' || c == '{') {st.push(c);} else {if (st.empty()) return false;char top = st.top();st.pop();if ((c == ')' && top != '(') ||(c == ']' && top != '[') ||(c == '}' && top != '{')) {return false;}}}return st.empty();
}

10.3 瀏覽器歷史記錄

cpp

class BrowserHistory {stack<string> backStack;stack<string> forwardStack;
public:void visit(string url) {backStack.push(url);while (!forwardStack.empty()) forwardStack.pop();}void back() {if (backStack.size() > 1) {forwardStack.push(backStack.top());backStack.pop();}}string current() {return backStack.top();}
};

十一、總結與展望

本文通過完整代碼示例和深度解析,系統闡述了C++ STL Stack的核心特性:

  • ?LIFO原則的完美實現
  • 底層容器適配器的靈活選擇
  • 高效O(1)時間復雜度的操作

?選擇建議?:

  • 需要嚴格后進先出 → 優先選擇stack
  • 需要先進先出 → 使用queue
  • 需要優先級處理 → 選擇priority_queue

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/78591.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/78591.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/78591.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Golang | 自行實現并發安全的Map

核心思路&#xff0c;讀寫map之前加鎖&#xff01;哈希思路&#xff0c;大map化分為很多個小map

Mac 「brew」快速安裝MySQL

安裝MySQL 在 macOS 上安裝 MySQL 環境可以通過Homebrew快速實現&#xff0c;以下是步驟指南&#xff1a; 方法 1&#xff1a;使用 Homebrew 安裝 MySQL 1. 安裝 Homebrew 如果尚未安裝 Homebrew&#xff0c;可以通過以下命令安裝&#xff1a; /bin/bash -c "$(curl -…

【數字孿生世界的搭建之旅:從0到1理解飛渡平臺】

數字孿生世界的搭建之旅&#xff1a;從0到1理解飛渡平臺 前言&#xff1a;數字分身的魔法 想象一下&#xff0c;如果你能在現實世界之外&#xff0c;創造一個物理世界的"分身"&#xff0c;這個分身能完美復制現實中的一切變化&#xff0c;甚至可以預測未來可能發生…

【漏洞復現】Struts2系列

【漏洞復現】Struts2系列 1. 了解Struts21. Struts2 S2-061 RCE &#xff08;CVE-2020-17530&#xff09;1. 漏洞描述2. 影響版本3. 復現過程 1. 了解Struts2 Apache Struts2是一個基于MVC設計模式的Web應用框架&#xff0c;會對某些標簽屬性&#xff08;比如 id&#xff09;的…

[FPGA Video IP] Video Processing Subsystem

Xilinx Video Processing Subsystem IP (PG231) 詳細介紹 概述 Xilinx LogiCORE? IP Video Processing Subsystem (VPSS)&#xff08;PG231&#xff09;是一個高度可配置的視頻處理模塊&#xff0c;設計用于在單一 IP 核中集成多種視頻處理功能&#xff0c;包括縮放&#xf…

自動駕駛(ADAS)功能--相關名稱及縮寫

根據《道路車輛先進駕駛輔助系統&#xff08;ADAS&#xff09;術語及定義》GB/T 39263—2020&#xff0c;如下表格&#xff1a; 編號中文術語英文縮寫定義類別2.1.1先進駕駛輔助系統ADAS利用傳感、通信、決策及執行等裝置&#xff0c;實時監測駕駛員、車輛及行駛環境&#xff…

1.9軟考系統架構設計師:優秀架構設計師 - 超簡記憶要點、知識體系全解、考點深度解析、真題訓練附答案及解析

超簡記憶要點 1. 優秀架構師標準 ? 技術&#xff08;深度/廣度&#xff09; 實戰&#xff08;大型項目&#xff09; 素養&#xff08;溝通/業務前瞻&#xff09; 2. 演化路徑 &#x1f4c8; 積累&#xff08;技術/項目&#xff09; → 思維&#xff08;系統視角/抽象建模&…

(MySQL)庫的操作

目錄 創建數據庫 語法 創建數據庫實例 不使用可選項 使用可選項1 字符集和校驗規則 校驗規則對數據庫的影響 不區分大小寫 查看配置 添加可選項2 操縱數據庫 使用數據庫 查看數據庫 查看所有數據庫 查詢當前正在使用的數據庫名稱 顯示創建數據庫語句 修改數據庫…

10.ArkUI Grid的介紹和使用

ArkUI Grid 組件詳解與使用指南 Grid 是 ArkUI 中用于實現網格布局的容器組件&#xff0c;能夠以行和列的形式排列子組件。以下是 Grid 組件的詳細介紹和使用方法。 基本介紹 Grid 組件特點&#xff1a; 支持固定列數和自適應布局提供靈活的間距和排列控制支持滾動顯示大量…

目標檢測原理簡介

目標檢測是一類計算機視覺任務,簡單來說,目標檢測可被定義為在計算機中輸入一張圖像,計算機需要找出圖像中所有感興趣的目標(物體),確定它們的類別和位置,如圖一所示。目標檢測是計算機視覺領域的核心問題之一,相較于最原始的將整張圖片分類為某一類別,目標檢測不光可…

ZYNQ筆記(十四):基于 BRAM 的 PS、PL 數據交互

版本&#xff1a;Vivado2020.2&#xff08;Vitis&#xff09; 實驗任務&#xff1a; PS 將字符串數據寫入BRAM&#xff0c;再將數據讀取出來&#xff1b;PL 從 BRAM 中讀取數據&#xff0c;bing。通過 ILA 來觀察讀出的數據&#xff0c;與前面串口打印的數據進行對照&#xff0…

Python-Django系列—部件

部件是 Django 對 HTML 輸入元素的表示。部件處理 HTML 的渲染&#xff0c;以及從對應于部件的 GET&#xff0f;POST 字典中提取數據。 內置部件生成的 HTML 使用 HTML5 語法&#xff0c;目標是 <!DOCTYPE html>。例如&#xff0c;它使用布爾屬性&#xff0c;如 checked…

【Leetcode 每日一題】2799. 統計完全子數組的數目

問題背景 給你一個由 正 整數組成的數組 n u m s nums nums。 如果數組中的某個子數組滿足下述條件&#xff0c;則稱之為 完全子數組 &#xff1a; 子數組中 不同 元素的數目等于整個數組不同元素的數目。 返回數組中 完全子數組 的數目。 子數組 是數組中的一個連續非空序…

卷積神經網絡(二)

1 卷積運算的兩個問題&#xff1a; 1.1 圖像邊緣信息使用少 邊緣的像素點可能只會被用一次或者2次&#xff0c;中間的會用的更多。 1.2 圖像被壓縮 5*5的圖像&#xff0c;如果經過3*3的卷積核后&#xff0c;大小變成3*3的。 N*N的圖像&#xff0c;果經過F*F的卷積核后&#x…

組網技術-DHCP服務器,RIP協議,OSPF協議

1.DHCP Server提供三種IP地址分配策略&#xff1a; 手工分配地址 自動分配地址 n 動態分配地址 2.DHCP報文類型 DHCP DISCOVER(廣播)&#xff1a;用于尋址DHCP Server DHCP OFFER&#xff08;單播&#xff09;&#xff1a;攜帶分配給客戶端的IP地址 DHCP REQUEST&#xff08;…

反爬策略應對指南:淘寶 API 商品數據采集的 IP 代理與請求偽裝技術

一、引言? 在電商數據驅動決策的時代&#xff0c;淘寶平臺海量的商品數據極具價值。然而&#xff0c;淘寶為保障平臺安全和用戶體驗&#xff0c;構建了嚴密的反爬體系。當采集淘寶 API 商品數據時&#xff0c;若不采取有效措施&#xff0c;頻繁的請求極易觸發反爬機制&#x…

學習筆記(算法學習+Maven)

單調隊列優化多重背包 #include <bits/stdc.h> using namespace std; const int M 2010; const int N 20010; int q[N]; int hh 0, tt -1; int f[N]; int g[N]; int v[M], w[M], s[M]; int n, m; int main() { cin >> n >> m; for (int i 1; …

WPF之項目創建

文章目錄 引言先決條件創建 WPF 項目步驟理解項目結構XAML 與 C# 代碼隱藏第一個 "Hello, WPF!" 示例構建和運行應用程序總結相關學習資源 引言 Windows Presentation Foundation (WPF) 是 Microsoft 用于構建具有豐富用戶界面的 Windows 桌面應用程序的現代框架。它…

JAVAEE初階01

個人主頁 JavaSE專欄 JAVAEE初階01 操作系統 1.對下&#xff08;硬件&#xff09;管理各種計算機設備 2.對上&#xff08;軟件&#xff09;為各種軟件提供一個穩定的運行環境 線程 運行的程序在操作系統中以進程的形式存在 進程是系統分配資源的最小單位 進程與線程的關…

HTML快速入門-4:HTML <meta> 標簽屬性詳解

<meta> 標簽是 HTML 文檔頭部&#xff08;<head> 部分&#xff09;的重要元素&#xff0c;用于提供關于文檔的元數據&#xff08;metadata&#xff09;。這些數據不會直接顯示在頁面上&#xff0c;但對瀏覽器、搜索引擎和其他服務非常重要。 常用屬性 1. name 和 …