棧和隊列的模擬實現

棧和隊列的模擬實現

  • 容器適配器
  • priority_queue(優先級隊列)
    • priority_queue的使用
    • priority_queue的模擬實現:
  • 仿函數
    • 什么叫仿函數?
    • 需要自己實現仿函數的情況:
  • 棧的模擬實現
  • 隊列的模擬實現
  • deque(vector和list的縫合怪)
    • 為什么選擇deque作為stack和queue的底層默認容器?
    • deque的優缺點
  • vector和list的優缺點

容器適配器

容器適配器(Container Adapter) 是一種基于現有容器類(如 vector、deque、list 等)構建的 包裝器(Wrapper)。

1.容器適配器本身不直接管理數據存儲,而是依賴底層容器(稱為 底層容器 或 基礎容器)實現存儲和訪問操作。例如:

stack 默認基于 deque 實現。
queue 默認基于 deque 實現。
priority_queue 默認基于 vector 實現。

2.適配器會屏蔽底層容器的部分接口,僅暴露特定操作所需的接口。

棧(stack) 只允許在棧頂進行插入(push)和刪除(pop)操作,屏蔽了隨機訪問等功能。
隊列(queue) 只允許在隊尾插入(push)、隊頭刪除(pop),屏蔽了中間元素的操作。

3.底層容器可定制。

#include <stack>
#include <vector>
#include <list>// 使用 vector 作為底層容器
std::stack<int, std::vector<int>> stack1;// 使用 list 作為底層容器
std::stack<int, std::list<int>> stack2;

priority_queue(優先級隊列)

priority_queue的使用

int main()
{priority_queue<int> pq;//默認是大的優先級高(大堆)//變小堆//priority_queue<int,vector<int>,greater<int>> pq;pq.push(4);pq.push(1);pq.push(5);pq.push(7);pq.push(9);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;return 0;
}

大堆調試:
在這里插入圖片描述
小堆調試:
在這里插入圖片描述

priority_queue的模擬實現:

#include<vector>template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};namespace bit
{// 默認是大堆template<class T, class Container = vector<T>, class Compare = Less<T>>class priority_queue{public:void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);}void AdjustDown(int parent){// 先假設左孩子小size_t child = parent * 2 + 1;Compare com;while (child < _con.size())  // child >= n說明孩子不存在,調整到葉子了{// 找出小的那個孩子//if (child + 1 < _con.size() && _con[child] < _con[child + 1])if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){++child;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}const T& top(){return _con[0];}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};
}

仿函數

什么叫仿函數?

仿函數:本質是一個類,這個類重載operator(),他的對象可以像函數一樣使用

template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};// < 升序
// > 降序
template<class Compare>
void BubbleSort(int* a, int n, Compare com)
{for (int j = 0; j < n; j++){// 單趟int flag = 0;for (int i = 1; i < n - j; i++){//if (a[i] < a[i - 1])if (com(a[i], a[i - 1])){swap(a[i - 1], a[i]);flag = 1;}}if (flag == 0){break;}}
}int main()
{Less<int> LessFunc;Greater<int> GreaterFunc;// 函數對象(仿函數)本質是一個對象cout << LessFunc(1, 2) << endl;cout << LessFunc.operator()(1, 2) << endl;int a[] = { 9,1,2,5,7,4,6,3 };BubbleSort(a, 8, LessFunc);BubbleSort(a, 8, GreaterFunc);BubbleSort(a, 8, Less<int>());BubbleSort(a, 8, Greater<int>());return 0;
}

需要自己實現仿函數的情況:

1.類類型不支持比較大小。
2.支持比較大小,但是比較的邏輯不是你想要的。

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}class DateLess
{
public:bool operator()(Date* p1, Date* p2){return *p1 < *p2;}
};
//測試
priority_queue<Date*, vector<Date*>, DateLess> q2;priority_queue<Date*> q2;q2.push(new Date(2018, 10, 29));q2.push(new Date(2018, 10, 28));q2.push(new Date(2018, 10, 30));cout << *q2.top() << endl;q2.pop();cout << *q2.top() << endl;q2.pop();cout << *q2.top() << endl;q2.pop();

棧的模擬實現

#include<deque>namespace bit
{// Container適配轉換出stacktemplate<class T, class Container = deque<T>>//deque:vector和list的縫合怪class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const T& top() const{return _con.back();}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};}

隊列的模擬實現

#include<deque>namespace bit
{// Container適配轉換出queuetemplate<class T, class Container = deque<T>>class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}const T& front() const{return _con.front();}const T& back() const{return _con.back();}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};
}

deque(vector和list的縫合怪)

為什么選擇deque作為stack和queue的底層默認容器?

stack是一種后進先出的特殊線性數據結構,因此只要具有push_back()和pop_back()操作的線性結構,都可以作為stack的底層容器,比如vector和list都可以;queue是先進先出的特殊線性數據結構,只要具有push_back和pop_front操作的線性結構,都可以作為queue的底層容器,比如list。但是STL中對stack和queue默認選擇deque作為其底層容器,主要是因為:

  1. stack和queue不需要遍歷(因此stack和queue沒有迭代器),只需要在固定的一端或者兩端進行操作。
  2. 在stack中元素增長時,deque比vector的效率高(擴容時不需要搬移大量數據);queue中的元素增長時,deque不僅效率高,而且內存使用率高。結合了deque的優點,而完美的避開了其缺陷。

deque的優缺點

在這里插入圖片描述

vector和list的優缺點

在這里插入圖片描述

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

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

相關文章

idea本地debug斷點小技巧

idea本地debug斷點小技巧 簡單的設置斷點條件 斷點后&#xff0c;右鍵這個斷點&#xff0c;可以在 condition 中填寫能得出布爾的表達式 a 1 你如果寫如下&#xff0c;表示先給他賦值&#xff0c;然后斷住 a 2; true 斷點后設置某個變量的值 在 debug 區域可以設置變量…

Oracle中如何解決FREE BUFFER WAITS

基于性能上的考慮&#xff0c;服務器進程在掃描LRU主列的同時&#xff0c;會將臟塊移至LRU-W列&#xff0c;如果發現沒有足夠可用&#xff08;可替換&#xff09;的BUFFER CACHE&#xff0c;進程并不會無止盡地掃描整條LRU主列&#xff0c;而是在掃描到某個閥值&#xff08;該閥…

Git命令使用全攻略:從創建分支到合并的完整流程

Git命令使用全攻略&#xff1a;從創建分支到合并的完整流程 引言一、初始化項目與基礎配置1.1 克隆遠程倉庫1.2 查看當前分支狀態 二、創建與管理分支2.1 從main分支創建新功能分支2.2 查看分支列表2.3 提交代碼到新分支2.4 推送分支到GitHub 三、版本發布與標簽管理3.1 創建輕…

MATLAB跳動的愛心

520&#xff0c;一個會動的心~~~ function particleHeart2 % author : slandarer% 所需匿名函數 col1Func(n) repmat([255,158,196]./255,[n,1])repmat([-39,-81,-56]./255,[n,1]).*rand([n,1]); col2Func(n) repmat([118,156,216]./255,[n,1])repmat([137,99,39].*.1./255,[n,…

Go的單測gomock及覆蓋率命令

安裝gomock&#xff1a; go get github.com/golang/mock/gomockgo get github.com/golang/mock/mockgen 使用 mockgen 生成 mock 代碼: 參考 mockgen -sourceservice/user.go -destinationservice /mocks/mock_user_service.go -packagemocks go test -coverprofilecoverage.ou…

vue添加loading后修復頁面渲染問題

問題&#xff1a;想要通過選擇流程&#xff08;1&#xff09;后加載出角色信息&#xff08;2&#xff09; 選擇后無法展示經過排查&#xff0c;再調用接口給角色數組賦值后&#xff0c;頁面在接口調用完之前就已經渲染完成。接口是采用的異步加載解決&#xff1a;loadingRoles…

Python入門手冊:Python簡介,什么是Python

在當今數字化時代&#xff0c;編程語言猶如一把把神奇的鑰匙&#xff0c;能夠開啟通往技術世界的大門。而Python&#xff0c;無疑是其中最閃耀的一顆明星。今天&#xff0c;就讓我們一起走進Python的世界&#xff0c;從它的起源、應用領域以及優缺點三個方面&#xff0c;來全面…

用PyTorch在超大規模下訓練深度學習模型:并行策略全解析

我猜咱們每個人肯定都累壞了&#xff0c;天天追著 LLM 研究社區跑&#xff0c;感覺每天都冒出個新的最牛模型&#xff0c;把之前的基準都給打破了呢。要是你好奇為啥創新速度能這么快&#xff0c;那主要就是研究人員能夠在超大規模下訓練和驗證模型啦&#xff0c;這全靠并行計算…

提示工程(Prompt Engineering)應用技巧

Prompt&#xff08;提示&#xff09;就是用戶與大模型交互輸入的代稱。即我們給大模型的輸入稱為 Prompt&#xff0c;而大模型返回的輸出一般稱為 Completion。 Prompt 需要清晰明確地表達需求&#xff0c;提供充足上下文&#xff0c;使語言模型能夠準確理解我們的意圖。更長、…

[原創](現代Delphi 12指南):[macOS 64bit App開發]: 如何獲取目錄大小?

[作者] 常用網名: 豬頭三 出生日期: 1981.XX.XX 企鵝交流: 643439947 個人網站: 80x86匯編小站 編程生涯: 2001年~至今[共24年] 職業生涯: 22年 開發語言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 開發工具: Visual Studio、Delphi、XCode、…

Unity入門學習(四)3D數學(4)之四元數Quaternion

目錄 一、什么是四元數 二、和歐拉角的關聯以及為什么會出現四元數 三、四元數的基本組成 Unity中的表示&#xff1a; 四、四元數Quaternion這個類中具有的屬性和方法 常用屬性 核心方法 五、四元數之間的計算 1. 叉乘&#xff08;組合旋轉&#xff09; 2. 點積&#…

活體檢測接口全面評測:2025年活體檢測選擇指南

一、活體檢測&#xff1a;數字化時代的身份驗證基石 活體檢測是一種通過分析人體生物特征動態變化來驗證身份真實性的技術&#xff0c;其核心在于區分真實人體與偽造樣本&#xff08;如照片、視頻、3D 面具等&#xff09;。技術原理主要基于以下維度&#xff1a; 多模態數據采…

物聯網工程畢業設計課題實踐指南

1. 智能家居控制系統 1.1 基于ZigBee的智能家居控制 實踐過程 硬件選型主控:CC2530/CC2531傳感器:溫濕度、光照、人體紅外執行器:繼電器、電機、LED燈系統架構 A[傳感器層] --> B[ZigBee網絡] B --> C[網關] C --> D[云平臺] D --> E[手機APP] 開…

電網中竊電分析:概念、算法與應用

一、引言 在現代電力系統中&#xff0c;竊電行為是一個嚴重影響電網經濟運行和供電秩序的問題。竊電不僅導致供電企業的經濟損失&#xff0c;破壞了電力市場的公平性&#xff0c;還可能對電網的安全穩定運行構成威脅&#xff0c;甚至引發安全事故。隨著科技的不斷進步&#xff…

一洽小程序接入說明

接入說明 文檔以微信小程序作為示例介紹&#xff0c;其他小程序接入操作與此類似 1、添加校驗文件 開發者使用微信小程序提供的 webview 組件可以實現打開一洽的H5對話 小程序的“域名配置”中添加一洽的對話域名地址&#xff0c;需要獲取校驗文件提供給一洽放在域名根目錄下…

【數據結構 -- AVL樹】用golang實現AVL樹

目錄 引言定義旋轉方式LL型RR型LR型RL型 實現結構獲取結點高度平衡因子更新高度左旋右旋插入結點中序遍歷 引言 AVL樹&#xff0c;基于二叉搜索樹通過平衡得到 前面我們知道&#xff0c;通過&#x1f517;二叉搜索樹可以便捷快速地查找到數據&#xff0c;但是當序列有序時&am…

PyTorch圖像識別模型和圖像分割模型體驗

文章目錄 倉庫地址練習&#xff1a;圖像自動識別模型數據集說明模型訓練和保存導入數據集搭建神經網絡訓練和保存實現 模型測試測試代碼測試結果 練習&#xff1a;圖像自動分割模型模型訓練和保存加載數據集搭建神經網絡訓練和保存 模型測試測試代碼測試效果 倉庫地址 圖像識別…

威綸通觸摸屏IP地址設定步驟及程序下載指南

在使用威綸通觸摸屏時&#xff0c;正確設定IP地址以及完成程序下載是確保其正常運行和實現功能的關鍵步驟。本文將詳細介紹威綸通觸摸屏IP地址設定步驟及程序下載的方法。 一、IP地址設定步驟 &#xff08;一&#xff09;前期準備 確保威綸通觸摸屏已經通電并啟動&#xff0…

一文讀懂|大模型智能體互操作協議:MCP/ACP/A2A/ANP

導讀 隨著推理大模型的出現&#xff08;deepseek&#xff0c;Qwen3等&#xff09;&#xff0c;進一步地推進了大模型的智能體系統發展。然而&#xff0c;如何使智能體更好的調用外部工具&#xff0c;智能體與智能體之間如何有機地協作&#xff0c;仍然沒有一個完美的答案。這篇…

前端下載ZIP包方法總結

在前端實現下載 ZIP 包到本地&#xff0c;通常有以下幾種方法&#xff0c;具體取決于 ZIP 包的來源&#xff08;靜態文件、后端生成、前端動態生成等&#xff09;&#xff1a; 方法 1&#xff1a;直接下載靜態文件&#xff08;最簡單&#xff09; 如果 ZIP 包是服務器上的靜態…