C++——stack和queue

目錄

stack的介紹和使用

stack的使用

queue的介紹和使用

queue的使用

容器適配器

deque的介紹

deque的缺陷

priority_queue的介紹和使用

priority_queue的使用

仿函數

反向迭代器


stack的介紹和使用

在原來的數據結構中已經介紹過什么是棧了,再來回顧一下:
  1. stack是一種容器適配器(關于什么是容器適配器之后下面會講到),專門用在具有后進先出操作的上下文環境中,其刪除只能從容器的一端進行元素的插入與刪除操作。
  2. stack是作為容器適配器被實現的,容器適配器是對特定類封裝作為其底層的容器,并提供一組特定的成員函數來訪問其元素,將特定類作為其底層的,元素特定容器的尾部(即棧頂)被壓入和彈出。
  3. stack的底層容器可以是任何標準的容器類模板或者一些其他特定的容器類。
  4. 標準容器vector、deque、list均符合這些需求,默認情況下,如果沒有為stack指定特定的底層容器,默認情況下使用deque(這個后面也會講)。

stack的使用

函數說明
接口說明
stack();
構造空的棧
bool empty() const;
檢測stack是否為空
size_t size() const;
返回stack中元素的個數
value_type& top();
返回棧頂元素的引用
void push(const value_type& val);
將元素val壓入stack中
void pop();
將stack中尾部的元素彈出

這些接口的使用都非常簡單,也不再過多說明。


queue的介紹和使用

  1. 隊列也是一種容器適配器,專門用于在FIFO上下文(first in first out 先進先出)中操作,其中從容器一端插入元素,另一端刪除元素。
  2. 隊列作為容器適配器實現,容器適配器即將特定容器類封裝作為其底層容器類,queue提供一組特定的成員函數來訪問其元素。元素從隊尾入隊列,從隊頭出隊列。
  3. 底層容器可以是標準容器類模板之一,也可以是其他專門設計的容器類。

  4. 標準容器類deque和list滿足了這些要求。默認情況下,如果沒有為queue實例化指定容器類,則使用標準容器deque。

queue的使用

函數聲明接口說明
queue();
構造空的隊列
bool empty() const;
檢測隊列是否為空

size_t size() const;

返回隊列中有效元素的個數
value_type& front();
返回隊頭元素的引用
value_type& back();
返回隊尾元素的引用
void push(const value_type& val);
在隊尾將元素val入隊列
void pop();
將隊頭元素出隊列


容器適配器

????????適配器是一種設計模式(設計模式是一套被反復使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結),該種模式是將一個類的接口轉換成客戶希望的另外一個接口

????????雖然stack和queue中也可以存放元素,但在STL中并沒有將其劃分在容器的行列,而是將其稱為容器適配器,這是因為stack和隊列只是對其他容器的接口進行了包裝,STL中stack和queue默認使用deque。


deque的介紹

????????deque(雙端隊列):是一種雙開口的"連續"空間的數據結構,雙開口不僅可以在頭尾兩端進行插入和刪除操作,而且時間復雜度為O(1),與vector比較,頭插效率高,不需要搬移元素;與list比較,空間利用率比較高。
????????deque并不是真正連續的空間,而是由一段段連續的小空間拼接而成的,實際deque類似于一個動態的二維數組,其底層結構如下圖所示:
????????從網上找了一張圖片,雙端隊列底層是一段假象的連續空間,實際是分段連續的,為了維護其“整體連續”以及隨機訪問的假象,落在了deque的迭代器身上,因此deque的迭代器設計就比較復雜。
????????圖中的cur指向當前數據,first和last表示buffer開始和結束,node反向指向中控器,方便找下一個buffer。

deque的缺陷

????????與vector相比,deque的優勢是:頭插和頭刪時,不需要搬移元素,效率高,而且在擴容時,也不需要搬移大量的元素,因此其效率比vector高的。
????????與list比較,其底層是連續空間,空間利用率比較高,不需要存儲額外字段。
????????但是,deque有一個致命缺陷:不適合遍歷,因為在遍歷時,deque的迭代器要頻繁的去檢測其是否移動到某段小空間的邊界,導致效率低下;中間插入刪除效率不高。而序列式場景中,可能需要經常遍歷,因此在實際中,需要線性結構時,大多數情況下優先考慮vector和list,deque的應用并不多,而目前能看到的一個應用就是,STL用其作為stack和queue的底層數據結構。
?
結論:
  1. 頭尾插入刪除非常適合,相比于vector和list,更適合做stack和queue的默認適配器。
  2. 中間插入刪除多,使用list。
  3. 隨機訪問多,使用vector。

priority_queue的介紹和使用

priority_queue是優先級隊列

  1. 優先隊列是一種容器適配器,根據嚴格的弱排序標準,它的第一個元素總是它所包含的元素中最大的。
  2. 類似于堆,在堆中可以隨時插入元素,并且只能檢索最大堆元素(優先隊列中位于頂部的元素)。
  3. 優先隊列被實現為容器適配器,容器適配器即將特定容器類封裝作為其底層容器類,queue提供一組特定的成員函數來訪問其元素。元素從特定容器的“尾部”彈出,其稱為優先隊列的頂部。
  4. 底層容器可以是任何標準容器類模板,也可以是其他特定設計的容器類。容器應該可以通過隨機訪問迭代器訪問。
  5. 標準容器類vector和deque滿足這些需求。默認情況下,如果沒有為特定的priority_queue類實例化指定容器類,則使用vector。?
  6. 需要支持隨機訪問迭代器,以便始終在內部保持堆結構。容器適配器通過在需要時自動調用算法函數make_heap、push_heap和pop_heap來自動完成此操作。

priority_queue的使用

????????優先級隊列默認使用vector作為其底層存儲數據的容器,在vector上又使用了堆算法將vector中元素構造成堆的結構,因此priority_queue就是堆,所有需要用到堆的時候,都可以考慮使用priority_queue。注意:默認情況下priority_queue是大堆。
函數聲明接口說明
priority_queue();
構造一個空的優先級隊列
bool empty() const;
檢測優先級隊列是否為空
const value_type& top() const;
返回優先級隊列中堆頂元素
void push(const value_type& x)在優先級隊列中插入x
void pop()刪除優先級隊列中的堆頂元素
template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type>>
class priority_queue; // 第一個模板參數是隊列中的元素類型,第二個是用什么容器,第三個決定是大堆還是小堆

仿函數

? ? ? ? 仿函數,有點地方也叫做函數對象,這其實就是一個類,這個類重載了一個operator()。

class less
{operator()(const int& l, const int& r){public:return l < r;}
};int main()
{less fun; // 這里的fun并不是一個函數,而是一個類對象,可以像函數一樣使用fun(1, 2); // 它的本質是在調用fun.opeartor()(1, 2),所以這里返回值應該是1return 0;
}
// 所以這樣好用的不該拘泥于整型,可以改成模板
template<class T>
class less
{operator()(const T& l, const T& r) const{public:return l < r;}
};// 既然有小于,就有大于
template<class T>
class greater
{operator()(const T& l, const T& r) const{public:return l > r;}
};int main()
{less<int> fun1;fun1(1, 2);greater<int> func2;func2(2, 1);return 0;
}
int main()
{// 使用優先級隊列,顯示傳第三個模板參數就是這樣的,默然就是大堆,想要建小堆就改成greater<int>priority_queue<int, vector<int>, less<int>> pq;// 當然要注意的是,這里傳入的是類型,相比于sort函數,傳入的是對象,這就可以使用匿名對象vector<int> v(5, 5);sort(v.begin(), v.end(), less<int>()); // sort默認排的升序,想要降序就傳入greater<int>()return 0;
}

反向迭代器

????????前面講到了正向迭代器的使用,那也要說一下反向迭代器的實現,反向迭代器是一種反向遍歷容器的迭代器。也就是,從最后一個元素到第一個元素遍歷容器。反向迭代器將自增(和自減)的含義反過來了:對于反向迭代器,++運算將訪問前一個元素,而 - -運算則訪問下一個元素。

// 復用,迭代器適配器
template<class Iterator, class Ref, class Ptr>
struct __reverse_iterator
{iterator _cur; // 使用正向迭代器構造一個反向迭代器typedef __reverse_iterator<Iterator> RIterator;__reverse_iterator(Iterator it):_cur(it){}RIterator operator++() // 注意這里只有前置++和--,后置是差不多的{--_cur;return *this;}RIterator operator--(){++ _cur;return *this;}Ref operator*() // 返回引用類型{auto tmp = _cur;--tmp;return *tmp;// 這里這么寫的原因是,begin返回第一個位置的迭代器,end返回最后一個位置的迭代器// rbegin返回最后一個位置的迭代器,rend返回第一個位置前一個的迭代器// 寫的時候可以復用begin和end,rbegin返回end位置,rend返回begin位置// 這里的cur就是構造的反向迭代器,先--后就是正確的位置}Ptr opeartor->() // 返回指針{// return _cur.operator->();return &(operator*());}bool operator!=(const RIterator& it){return _cur != it._cur;}
};

????????這樣可以適配生成某些容器的反向迭代器,有些容器比較特殊,所以不支持,比如單鏈表forward_list,它只支持++并不支持- -;unordered_map和unordered_set也是不支持的,這就要到后面再說了。

? ? ? ? 從某些功能的角度分析,迭代器也可以分成幾類:

  • forward_iterator,它只支持++,因為它是單向的。容器有:unordered_map,unordered_set,forward_list。
  • bidirectional_iterator,它支持++和- -,它是雙向的。容器有:list,map,set。
  • random_access_iterator,它不僅支持++和- -,還支持+和-,他是隨機的。容器有:deque,vector。

????????這里的迭代器從下到上是一種繼承關系,關于什么是繼承后面也會講。簡單理解一下,隨機迭代器也是雙向的,拿sort函數和reverse函數舉例,sort函數接口的參數類型就是隨機迭代器的,reverse函數接口就是雙向的,但是可以用隨機類型的容器調用reverse這個函數;相對的,雙向類型的容器就不能調用sort這個函數。vector可以調用reverse函數,list不能調用sort函數(algorithm庫中的)。

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

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

相關文章

視頻監控平臺EasyCVR+智能分析網關+物聯網,聯合打造智能環衛監控系統

一、背景介紹 城市作為人們生活的載體&#xff0c;有著有無數樓宇和四通八達的街道&#xff0c;這些建筑的整潔與衛生的背后&#xff0c;是無數環衛工作人員的努力。環衛工人通過清理垃圾、打掃街道、清洗公共設施等工作&#xff0c;保持城市的整潔和衛生&#xff0c;防止垃圾…

【機器學習 | 白噪聲檢驗】檢驗模型學習成果 檢驗平穩性最佳實踐,確定不來看看?

&#x1f935;?♂? 個人主頁: AI_magician &#x1f4e1;主頁地址&#xff1a; 作者簡介&#xff1a;CSDN內容合伙人&#xff0c;全棧領域優質創作者。 &#x1f468;?&#x1f4bb;景愿&#xff1a;旨在于能和更多的熱愛計算機的伙伴一起成長&#xff01;&#xff01;&…

C++ Day09 容器

C-STL01- 容器 引入 我們想存儲多個學員的信息 , 現在學員數量不定 通過以前學習的知識 , 我們可以創建一個數組存儲學員的信息 但是這個數組大小是多少呢 ? 過大會導致空間浪費 , 小了又需要擴容 對其中的數據進行操作也較為復雜 每次刪除數據后還要對其進行回收等操作…

cookie的跨站策略 跨站和跨域

借鑒&#xff1a;Cookie Samesite簡析 - 知乎 (zhihu.com) 1、跨站指 協議、域名、端口號都必須一致 2、跨站 頂級域名二級域名 相同就行。cookie遵循的是跨站策略

PowerDesigner異構數據庫轉換

主要流程:sql->pdm->cdm->other pdm->sql 1.根據sql生成pdm 2.根據pdm生成cdm 3.生成其他類型數據庫pdm

【Java】認識String類

文章目錄 一、String類的重要性二、String類中的常用方法1.字符串構造2.String對象的比較3.字符串查找4.轉換5.字符串替換6.字符串拆分7.字符串截取8.其他操作方法9.字符串的不可變性10.字符串修改 三、StringBuilder和StringBuffer 一、String類的重要性 在C語言中已經涉及到…

C語言第二十五彈--打印菱形

C語言打印菱形 思路&#xff1a;想要打印一個菱形&#xff0c;可以分為上下兩部分&#xff0c;通過觀察可以發現上半部分星號的規律是 1 3 5 7故理解為 2對應行數 1 &#xff0c;空格是4 3 2 1故理解為 行數-對應行數-1。 上半部分代碼如下 for (int i 0;i < line;i){//上…

Vivado Modelsim聯合進行UVM仿真指南

打開Vivado&#xff0c;打開對應工程&#xff0c;點擊左側Flow Navigator-->PROJECT MANAGER-->Settings&#xff0c;打開設置面板。點擊Project Settings-->Simulation選項卡&#xff0c;如下圖所示。 將Target simulator設為Modelsim Simulator。 在下方的Compil…

OpenGL 繪制圓形平面(Qt)

文章目錄 一、簡介二、代碼實現三、實現效果一、簡介 這里使用一種簡單的思路來生成一個圓形平面: 首先,我們需要生成一個單位圓,半徑為1,法向量為(0, 0, 1),這一步我們可以使用一些函數生成圓形點集。之后,指定面片的索引生成一個圓形平面。當然這里為了后續管理起來方便…

Py之PyMuPDF:PyMuPDF的簡介、安裝、使用方法之詳細攻略

Py之PyMuPDF&#xff1a;PyMuPDF的簡介、安裝、使用方法之詳細攻略 目錄 PyMuPDF的簡介 PyMuPDF的安裝 PyMuPDF的使用方法 1、基礎用法 PyMuPDF的簡介 PyMuPDF是一個高性能的Python庫&#xff0c;用于PDF(和其他)文檔的數據提取&#xff0c;分析&#xff0c;轉換和操作。 …

Matrix

Matrix 如下是四種變換對應的控制參數&#xff1a; Rect 常用的一個“繪畫相關的工具類”&#xff0c;常用來描述長方形/正方形&#xff0c;他只有4個屬性&#xff1a; public int left; public int top; public int right; public int bottom; 這4個屬性描述著這一個“方塊…

基于JavaWeb+SSM+Vue校園水電費管理小程序系統的設計和實現

基于JavaWebSSMVue校園水電費管理小程序系統的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄Java項目精品實戰案例《500套》 源碼獲取 源碼獲取入口 Lun文目錄 摘 要 III Abstract 1 1 系統概述 2 1.1 概述 2 1.2課題意義 3 1.3 主要內容 3…

使用【畫圖】軟件修改圖片像素、比例和大小

打開電腦畫圖軟件&#xff0c;點擊開始 windows附件 畫圖 在畫圖軟件里選擇需要調整的照片&#xff0c;點擊文件 打開 在彈出窗口中選擇照片后點擊打開 照片在畫圖軟件中打開后&#xff0c;對照片進行調整。按圖中順序進行 確定后照片會根據設定的值自動調整 保存…

Codeforces Round 745 (Div. 2)(C:前綴和+滑動窗口,E:位運算加分塊)

Dashboard - Codeforces Round 745 (Div. 2) - Codeforces A&#xff1a; 答案就是2n!/2, 對于當前滿足有k個合法下標的排列&#xff0c;就是一個n-k個不合法的下標的排列&#xff0c; 所以每一個合法排列都相反的存在一個 對稱性 #include<bits/stdc.h> using nam…

【Redisson】基于自定義注解的Redisson分布式鎖實現

前言 在項目中&#xff0c;經常需要使用Redisson分布式鎖來保證并發操作的安全性。在未引入基于注解的分布式鎖之前&#xff0c;我們需要手動編寫獲取鎖、判斷鎖、釋放鎖的邏輯&#xff0c;導致代碼重復且冗長。為了簡化這一過程&#xff0c;我們引入了基于注解的分布式鎖&…

JS獲取時間戳的五種方法

一、JavasCRIPT時間轉時間戳 JavaScript獲得時間戳的方法有五種&#xff0c;后四種都是通過實例化時間對象new Date() 來進一步獲取當前的時間戳&#xff0c;JavaScript處理時間主要使用時間對象Date。 方法一&#xff1a;Date.now() Date.now()可以獲得當前的時間戳&#x…

思維模型 等待效應

本系列文章 主要是 分享 思維模型 &#xff0c;涉及各個領域&#xff0c;重在提升認知。越是等待&#xff0c;越是焦慮。 1 等待效應的應用 1.1 等待效應在管理中的應用 西南航空公司是一家美國的航空公司&#xff0c;它在管理中運用了等待效應。西南航空公司鼓勵員工在工作中…

快速學會使用Python3.12的新特性

一、 PEP 695: 類型形參語法的革新 PEP 695 在 Python 3.12 中引入了一種新穎且更為清晰的方式來定義泛型類和函數&#xff0c;旨在提升類型參數的明確性和簡潔性。這個提案不僅改善了類型系統的可讀性&#xff0c;還增強了其功能性。以下是這些變化的詳細概述&#xff1a; 1…

(四)C語言之符號常量概述

&#xff08;四&#xff09;C語言之符號常量概述 一、符號常量概述 一、符號常量概述 在程序中使用像300,20等這樣的等類似的“幻數”不是一個好的習慣&#xff0c;它們無法向閱讀該程序的人提供更多有用的信息&#xff0c;從而使得修改程序變得困難。處理這種幻數的一種方法是…

unreal 指定windows SDK

路徑 &#xff1a; “C:\Users\Administrator\AppData\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml” 在Configuration中添加 <WindowsPlatform><WindowsSdkVersion>10.0.20348.0</WindowsSdkVersion></WindowsPlatform>示例&…