容器適配器-stack棧

C++標準庫不只是包含了順序容器,還包含一些為滿足特殊需求而設計的容器,它們提供簡單的接口。

這些容器可被歸類為容器適配器(container adapter),它們是改造別的標準順序容器,使之滿足特殊需求的新容器。

適配器:也稱配置器,把一種接口轉為另一種接口。

有三種標準的 容器適配器: stack(棧)、queue(隊列)和priority queue(優先級隊列)。 priority queue就是“根據排序準則,自動將元素排序”的隊列,其所謂“下一個””元素總是擁有最高優先級。

stack棧

stack 棧是一種只在一端(棧頂)進行數據插入(入棧)和刪除(出棧)的數據結構,它滿足后進先出(LIFO)的特性。

使用push(入棧)將數據放入stack,使用pop(出棧)將元素從容器中移除。 POP PUSH棧頂TOP棧底

?

使用stack,必須包含頭文件:

#include <stack>

在頭文件中,class stack定義如下:

namespace std{template <typename T,typename Container = deque<T>>class stack;
}

第一個參數T代表類型,第二個參數用來定義stack內部存放數據的容器,默認為deque。之所以選擇deque而非vector,是因為deque移除數據時可能會釋放內存,并在插入數據需要擴容時不需要復制所有的數據。

例如,以下定義了一個元素類型為整數的 stack:

std::stack<int>?st;

stack 只是很單純地把各項操作轉化為內部容器對應的函數調用。你可以使用任何支持 back()、push_back()和pop_back()成員函數的標準容器支持 stack。例如你可以使用 vector或list 來存放數據:

stack<int,vector<int>> st;//整型棧,使用vector存放數據

注意:forword_list和array不可以作為其容器

定義及初始化

#include <iostream>
#include <stack>
#include <vector>
#include <list>
using namespace std;int main()
{stack <char> s1;//創建一個默認的棧,最常用stack <char, deque<char> > s2;//顯示創建用deque保存數據的棧,和s1等價stack <int, vector<int> > s3;//創建用vector保存數據的棧stack <int, list<int> > s4;//創建用list保存數據的棧return 0;
}

先創建一個空的棧,然后往里面存放數據。

常用操作

stack棧的操作比較簡單,不支持迭代器和運算符,只有幾個簡單的成員函數。 empty成員函數

empty成員函數

判斷棧是否為空。

//判空
bool IsEmpty(PLStack ps)
{return ps->next == NULL;
}

pop成員函數

出棧函數,刪除棧頂元素。

//獲取棧頂元素的值,并且刪除
bool Pop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;LSNode* p = ps->next;ps->next = ps->next->next;free(p);return true;
}

push成員函數

入棧函數,往棧頂添加數據。

//往棧中入數據(入棧操作)
bool Push(PLStack ps, int val)
{assert(ps != NULL);if (ps == NULL)return false;LSNode* p = (LSNode*)malloc(sizeof(LSNode));assert(p != NULL);p->date = val;p->next = ps->next;ps->next = p;return false;
}

size成員函數

返回棧的數據個數。

//獲取棧中有效數據的個數
int GetLength(PLStack ps)
{assert(ps != NULL);if (ps == NULL)return 0;int count = 0;for (LSNode* p = ps->next; p != NULL; p = p->next){count++;}return count;
}

top成員函數

返回棧頂元素的引用。

//獲取棧頂元素的值,但不刪除
bool  GetTop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;return true;
}

棧的實現方式?

鏈表實現:鏈表實現棧則更加靈活,它不需要預先分配固定大小的內存空間,適用于棧的大小動態變化且難以預估的場景。在鏈表實現中,每個節點包含數據和指向下一個節點的指針。棧頂對應鏈表的頭節點,入棧和出棧操作都在鏈表頭部進行,時間復雜度同樣為 O (1)。

.h文件

#pragma once//鏈式棧
typedef struct LSNode
{int date;struct LSNode* next;
}LSNode, * PLStack;//初始化
void InitStack(PLStack ps);//往棧中入數據(入棧操作)
bool Push(PLStack ps, int val);//獲取棧頂元素的值,但不刪除
bool  GetTop(PLStack ps, int* rtval);//獲取棧頂元素的值,并且刪除
bool Pop(PLStack ps, int* rtval);//判空
bool IsEmpty(PLStack ps);//獲取棧中有效數據的個數
int GetLength(PLStack ps);//清空所有的數據
void Clear(PLStack ps);//銷毀
void Destroy(PLStack ps);

.cpp文件

#include "Istak.h"
#include <iostream>
#include <cassert>
using namespace std;//初始化
void InitStack(PLStack ps)
{assert(ps != NULL);if (ps == NULL)return;ps->next = NULL;
}//往棧中入數據(入棧操作)
bool Push(PLStack ps, int val)
{assert(ps != NULL);if (ps == NULL)return false;LSNode* p = (LSNode*)malloc(sizeof(LSNode));assert(p != NULL);p->date = val;p->next = ps->next;ps->next = p;return false;
}//獲取棧頂元素的值,但不刪除
bool  GetTop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;return true;
}//獲取棧頂元素的值,并且刪除
bool Pop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;LSNode* p = ps->next;ps->next = ps->next->next;free(p);return true;
}//判空
bool IsEmpty(PLStack ps)
{return ps->next == NULL;
}//獲取棧中有效數據的個數
int GetLength(PLStack ps)
{assert(ps != NULL);if (ps == NULL)return 0;int count = 0;for (LSNode* p = ps->next; p != NULL; p = p->next){count++;}return count;
}//清空所有的數據
void Clear(PLStack ps)
{Destroy(ps);
}//銷毀
void Destroy(PLStack ps)
{LSNode* p;while (ps->next != NULL){p = ps->next;ps->next = p->next;free(p);}
}

棧的應用場景?

1.表達式求值

在數學表達式求值中,棧發揮著關鍵作用。例如,對于后綴表達式(逆波蘭表達式),我們可以利用棧來高效地計算結果。后綴表達式將運算符放在操作數之后,避免了括號帶來的優先級判斷復雜性。計算時,從左到右掃描后綴表達式,遇到操作數就將其入棧,遇到運算符則從棧中彈出相應數量的操作數進行運算,并將結果入棧。最終,棧頂元素即為表達式的計算結果。以表達式 “3 4 + 2 *” 為例,計算過程如下:?

掃描到 3,入棧,棧:[3]?

掃描到 4,入棧,棧:[3, 4]?

掃描到 +,彈出 4 和 3,計算 3 + 4 = 7,將 7 入棧,棧:[7]?

掃描到 2,入棧,棧:[7, 2]?

掃描到 *,彈出 2 和 7,計算 7 * 2 = 14,將 14 入棧,棧:[14]??

最終結果為 14

2.括號匹配

在編譯器和文本編輯器中,常常需要檢查代碼中的括號是否正確匹配,如圓括號、方括號和花括號。利用棧可以輕松解決這個問題。當遇到左括號時,將其入棧;遇到右括號時,從棧中彈出對應的左括號進行匹配。如果在匹配過程中棧為空或者匹配失敗,說明括號不匹配。例如,對于字符串 “{[()]}”,處理過程如下:?

遇到 {,入棧,棧:[{]?

遇到 [,入棧,棧:[{, []?

遇到 (,入棧,棧:[{, [, (]?

遇到 ),彈出 (進行匹配,棧:[{, []?

遇到 ],彈出 [進行匹配,棧:[{]?

遇到 },彈出 {進行匹配,棧:[]?

匹配成功

3.函數調用棧

在程序執行過程中,函數調用是通過棧來管理的。當一個函數被調用時,它的相關信息,如參數、局部變量和返回地址等,會被壓入棧中。當函數執行完畢返回時,這些信息會從棧中彈出,程序繼續執行調用函數的下一條指令。例如,在一個包含多個函數嵌套調用的程序中,棧記錄了函數調用的順序和狀態,確保函數能夠正確返回和繼續執行。假設函數 A 調用函數 B,函數 B 又調用函數 C,棧的狀態變化如下:?

調用 A,A 的相關信息入棧,棧:[A]?

A 中調用 B,B 的相關信息入棧,棧:[A, B]?

B 中調用 C,C 的相關信息入棧,棧:[A, B, C]?

C 執行完畢返回,C 的信息出棧,棧:[A, B]?

B 執行完畢返回,B 的信息出棧,棧:[A]?

A 執行完畢返回,A 的信息出棧,棧:[]

4.深度優先搜索(DFS)

在圖論和搜索算法中,深度優先搜索常常用棧來實現。在遍歷圖的過程中,從起始節點開始,將其入棧。然后,每次從棧中彈出一個節點,訪問該節點,并將其未訪問過的鄰接節點入棧,直到棧為空。這樣的方式使得搜索沿著一條路徑盡可能深地探索下去,直到無法繼續,然后回溯到上一個節點繼續探索其他路徑。

5.瀏覽器歷史記錄

我們日常使用的瀏覽器,其歷史記錄功能也運用了棧的思想。當我們依次訪問網頁 A、B、C 時,這些網頁依次被壓入棧中。當我們點擊 “后退” 按鈕時,就相當于執行出棧操作,從棧頂彈出當前頁面,回到上一個頁面。例如,訪問順序為 A -> B -> C,棧的狀態為 [C, B, A],點擊 “后退”,C 出棧,回到 B 頁面,棧變為 [B, A]

總結?

棧作為一種簡單而強大的數據結構,以其獨特的后進先出特性,在眾多領域展現出高效的應用價值。無論是復雜的算法實現,還是日常使用的軟件功能,棧都默默發揮著重要作用。通過對棧的概念、操作、實現方式以及應用場景的深入學習,我們不僅掌握了一種基礎的數據結構,更能在編程實踐中靈活運用它來解決各種實際問題。在未來的編程之旅中,希望你能充分利用棧的優勢,優化代碼,提升程序的性能和效率。讓我們繼續探索數據結構的奇妙世界,解鎖更多編程的奧秘!

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

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

相關文章

[250403] HuggingFace 新增檢查模型與電腦兼容性的功能 | Firefox 發布137.0 支持標簽組

目錄 Hugging Face 讓尋找兼容的 AI 模型變得更容易Firefox 137 版本更新摘要 Hugging Face 讓尋找兼容的 AI 模型變得更容易 Hugging Face 是一個流行的在線平臺&#xff0c;用于訪問開源人工智能 (AI) 工具和模型。該平臺推出了一項有用的新功能&#xff0c;允許個人輕松檢查…

.NET 創建MCP使用大模型對話二:調用遠程MCP服務

在上一篇文章.NET 創建MCP使用大模型對話-CSDN博客中&#xff0c;我們簡述了如何使用mcp client使用StdIo模式調用本地mcp server。本次實例將會展示如何使用mcp client模式調用遠程mcp server。 一&#xff1a;創建mcp server 我們創建一個天氣服務。 新建WebApi項目&#x…

Redis 中 Set(例如標簽) 和 ZSet(例如排行榜) 的詳細對比,涵蓋定義、特性、命令、適用場景及總結表格

以下是 Redis 中 Set 和 ZSet 的詳細對比&#xff0c;涵蓋定義、特性、命令、適用場景及總結表格&#xff1a; 1. 核心定義 數據類型SetZSet&#xff08;Sorted Set&#xff09;定義無序的、唯一的字符串集合&#xff0c;元素不重復。有序的、唯一的字符串集合&#xff0c;每個…

解決Spring參數解析異常:Name for argument of type XXX not specified

前言 在開發 Spring Boot 應用時&#xff0c;我們常遇到類似 java.lang.IllegalArgumentException: Name for argument not specified 的報錯。這類問題通常與方法參數名稱的解析機制相關&#xff0c;尤其在使用 RequestParam、PathVariable 等注解時更為常見。 一、問題現象與…

剛剛,OpenAI開源PaperBench,重塑頂級AI Agent評測

今天凌晨1點&#xff0c;OpenAI開源了一個全新的AI Agent評測基準——PaperBench。 這個基準主要考核智能體的搜索、整合、執行等能力&#xff0c;需要對2024年國際機器學習大會上頂尖論文的復現&#xff0c;包括對論文內容的理解、代碼編寫以及實驗執行等方面的能力。 根據O…

Golang封裝Consul 服務發現庫

以下是一個經過生產驗證的 Consul 服務發現封裝庫,支持注冊/注銷、健康檢查、智能發現等核心功能,可直接集成到項目中: package consulimport ("context""fmt""log""math/rand""net""os""sync"&quo…

自適應信號處理任務(過濾,預測,重建,分類)

自適應濾波 # signals creation: u, v, d N = 5000 n = 10 u = np.sin(np.arange(0, N/10., N/50000

PyTorch深度學習框架 的基礎知識

目錄 1.pyTorch檢查是否安裝成功 2.PyTorch的張量tensor 基礎創建方式&#xff08;三種&#xff09; 2.2用列表創建tensor 2.2使用元組創建 tensor 2.3使用ndarray創建創建 tensor 2.4 快速創建tensor的常用方法 3.pyTorch中的張量tensor的常用屬性 4. tensor中的基礎數據…

MySQL學習集--DDL

DDL 數據庫操作 查詢所有數據庫 SHOW DATABASES;查詢當前數據庫 SELECT DATABASE();創建 CREATE DATABASE[IF NOT EXISTS]數據庫名[DEFAULT CHARSET 字符集][COLLATE 排序規則];刪除 DROR DATABASE[IF EXISTS]數據庫名;使用 USE 數據庫名;表操作 創建表格 CREATE TABL…

Vue 3 中按照某個字段將數組分成多個數組

方法一&#xff1a;使用 reduce 方法 const originalArray [{ id: 1, category: A, name: Item 1 },{ id: 2, category: B, name: Item 2 },{ id: 3, category: A, name: Item 3 },{ id: 4, category: C, name: Item 4 },{ id: 5, category: B, name: Item 5 }, ];const grou…

LeetCode刷題 -- 48. 旋轉圖像

題目 算法題解&#xff1a;順時針旋轉矩陣&#xff08;90度&#xff09; 1. 算法描述 給定一個 n n 的二維矩陣&#xff0c;請將矩陣順時針旋轉 90 度。 例如&#xff1a; 輸入&#xff1a; [[1,2,3],[4,5,6],[7,8,9] ]輸出&#xff1a; [[7,4,1],[8,5,2],[9,6,3] ]2. 思…

Vulkan進階系列1 - Vulkan應用程序結構(完整代碼)

一: 概述 在前面的20多篇文章中,我們了解了Vulkan的基礎知識,和相關API的使用,接下來我們要從零開始寫一套完整Vulkan應用程序,在這個過程中加深對Vulkan中的各種概念的理解。 Vulkan 應用程序一般遵循 初始化 -> 運行循環 -> 資源清理 的結構,本實例也基本遵循了…

VTK的兩種顯示刷新方式

在類中先聲明vtk的顯示對象 vtkRenderer out_render; vtkVertexGlyphFilter glyphFilter; vtkPolyDataMapper mapper; // 新建制圖器 vtkActor actor; // 新建角色 然后在init中先初始化一下&#xff1a; out_rend…

【CSS3】04-標準流 + 浮動 + flex布局

本文介紹浮動與flex布局。 目錄 1. 標準流 2. 浮動 2.1 基本使用 特點 脫標 2.2 清除浮動 2.2.1 額外標簽法 2.2.2 單偽元素法 2.2.3 雙偽元素法(推薦) 2.2.4 overflow(最簡單) 3. flex布局 3.1 組成 3.2 主軸與側軸對齊方式 3.2.1 主軸 3.2.2 側軸 3.3 修改主…

詳細介紹一下C++的按位運算

在C中&#xff0c;按位運算&#xff08;Bitwise Operations&#xff09; 是直接對二進制位&#xff08;bit&#xff09;進行操作的低級運算&#xff0c;常用于處理硬件、優化性能、加密算法或底層資源管理。以下是按位運算符的詳細說明、示例和典型應用場景&#xff1a; 1.按位…

Flask與 FastAPI 對比:哪個更適合你的 Web 開發?

在開發 Web 應用時&#xff0c;Python 中有許多流行的 Web 框架可以選擇&#xff0c;其中 Flask 和 FastAPI 是兩款廣受歡迎的框架。它們各有特色&#xff0c;適用于不同的應用場景。本文將從多個角度對比這兩個框架&#xff0c;幫助你更好地選擇適合的框架來構建你的 Web 應用…

Python爬蟲第一戰(爬取優美圖庫網頁圖片)

本文是我在學習過程中記錄學習的點點滴滴,目的是為了學完之后鞏固一下順便也和大家分享一下,日后忘記了也可以方便快速的復習。 爬取網頁圖片 前言前言 今天學習的主要是關于如何利用Python爬取網頁圖片知識的理解和應用 # 1.獲取網頁信息,交給beautifulsoup # 2.獲取頁面里…

J1 ResNet-50算法實戰與解析

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習紀錄博客&#x1f356; 原作者&#xff1a;K同學啊 | 接輔導、項目定制 一、理論知識儲備 1. 殘差網絡的由來 ResNet主要解決了CNN在深度加深時的退化問題&#xff08;梯度消失與梯度爆炸&#xff09;。 雖然B…

Python入門(3):語句

目錄 1 基本語句 1.1 表達式語句 1.2 賦值語句 2 控制流語句 2.1 條件語句 2.2 循環語句 while循環&#xff1a; for循環&#xff1a; 2.3 流程控制語句 1. break語句&#xff1a;退出整個循環體 2. continue語句&#xff1a;只跳過本次循環&#xff0c;還會進…