[C++] STL_priority_queue(優先級隊列) 的使用及底層的模擬實現,容器適配器,deque的原理介紹

在這里插入圖片描述

文章目錄

  • 1、priority_queue
    • 1.1 priority_queue的介紹和使用
    • 1.2 priority_queue的使用
      • 模擬實現:
  • 2、容器適配器
    • 2.1 什么是適配器
    • 2.2 STL標準庫中stack和queue的底層結構
  • 3、deque
    • 3.1 deque的原理介紹
    • 3.2 deque的缺陷
  • 4、為什么選擇deque作為stack和queue的底層默認容器

1、priority_queue

1.1 priority_queue的介紹和使用

priority_queue文檔介紹
在這里插入圖片描述

翻譯:
1. 優先隊列是一種容器適配器 ,根據嚴格的弱排序標準,它的第一個元素總是它所包含的元素中最大的。
2. 此上下文類似于在堆中可以隨時插入元素,并且只能檢索最大堆元素(優先隊列中位于頂部的元素)。
3. 優先隊列被實現為容器適配器,容器適配器即將特定容器類封裝作為其底層容器類,queue提供一組特定的成員函數來訪問其元素。元素從特定容器的“尾部”彈出,其稱為優先隊列的頂部。
4. 底層容器可以是任何標準容器類模板,也可以是其他特定設計的容器類。容器應該可以通過隨機訪問迭代器訪問,并支持以下操作:
empty():檢測容器是否為空
size():返回容器中有效元素個數
front():返回容器中第一個元素的引用

push_back():在容器尾部插入元素
pop_back():刪除容器尾部元素

5. 標準容器類vector和deque滿足這些需求默認情況下,如果沒有為特定的priority_queue類實例化指定容器類,則使用 vector。
6. 需要支持隨機訪問迭代器,以便始終在內部保持堆結構。容器適配器通過在需要時自動調用算法函數make_heap、push_heap和pop_heap來自動完成此操作。

1.2 priority_queue的使用

優先級隊列默認使用vector作為其底層存儲數據的容器,在vector上又使用了堆算法將vector中元素構造成堆的結構,因此 priority_queue就是堆加粗樣式 所有需要用到堆的位置,都可以考慮使用priority_queue。注意: 默認情況下priority_queue是大堆。

函數聲明接口說明
priority_queue()/priority_queue(first,last)構造一個空的優先級隊列
empty( )檢測優先級隊列是否為空,是返回true,否則返回false
top( )返回優先級隊列中最大(最小元素),即堆頂元素
push()在優先級隊列中插入元素x
pop()刪除優先級隊列中最大(最小)元素,即堆頂元素

注意:
1、默認情況下,priority_queue是大堆。

#include <vector>
#include <queue>
#include <functional> // greater算法的頭文件int main()
{// 默認情況下,創建的是大堆,其底層按照小于號比較vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };priority_queue<int> q1;for (auto& e : v) q1.push(e);while (!q1.empty()){cout << q1.top() << " ";q1.pop();}cout << endl;// 如果要創建小堆,將第三個模板參數換成greater比較方式priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());while (!q2.empty()){cout << q2.top() << " ";q2.pop();}cout << endl;return 0;
}

在這里插入圖片描述

2、如果在priority_queue中放自定義類型的數據,用戶需要在自定義類型中提供 > 或者 < 的重載。

class Date
{
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);}friend ostream& operator<<(ostream& _cout, const Date& d){_cout << d._year << "-" << d._month << "-" << d._day;return _cout;}
private:int _year;int _month;int _day;
};void TestPriorityQueue()
{// 大堆,需要用戶在自定義類型中提供<的重載priority_queue<Date> q1;q1.push(Date(2018, 10, 29));q1.push(Date(2018, 10, 28));q1.push(Date(2018, 10, 30));cout << q1.top() << endl;// 如果要創建小堆,需要用戶提供>的重載priority_queue<Date, vector<Date>, greater<Date>> q2;q2.push(Date(2018, 10, 29));q2.push(Date(2018, 10, 28));q2.push(Date(2018, 10, 30));cout << q2.top() << endl;
}int main()
{TestPriorityQueue();return 0;
}

模擬實現:

我們剛已經了解到,priority_queue就是堆,并且默認是大堆,底層容器封裝的是vector,因此我們模擬實現priority_queue也是比較簡單的。

#include<vector>
#include<functional>
using namespace std;namespace lcx
{// 仿函數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 T, class Container = vector<T>, class Compare = Greater<T>>class priority_queue{public:priority_queue(){}template <class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first, last){for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){adjust_down(i);}}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}const T& top() const{return _con[0];}void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}private:void adjust_up(int child){int parent = (child - 1) / 2;while (child > 0){//if (_con[child] > _con[parent])if(comp(_con[child], _con[parent])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else break;}}void adjust_down(size_t parent){size_t child = parent * 2 + 1;while (child < _con.size()){//if (child + 1 < _con.size()//      && _con[child + 1] > _con[child])if(child + 1 < _con.size()&& comp(_con[child + 1], _con[child])){child++;}//if (_con[child] > _con[parent])if (comp(_con[child], _con[parent])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else break;}}private:Container _con;Compare comp;};
};

這里如果還有對堆不熟悉的同學我們可以看看我的另外一篇文章,專門講解堆的:C語言實現堆詳細版本

2、容器適配器

2.1 什么是適配器

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

2.2 STL標準庫中stack和queue的底層結構

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

3、deque

3.1 deque的原理介紹

deque(雙端隊列):是一種雙開口的"連續"空間的數據結構,雙開口的含義是:可以在頭尾兩端進行插入和刪除,且時間復雜度為O(1),與vector比較,頭插效率高,不需要搬移元素;與list比較,空間利用率比較高。

在這里插入圖片描述
deque并不是真正連續的空間,而是由一段段連續的小空間拼接而成的,實際deque類似于一個動態的二維數組,其底層結構如下圖所示:
在這里插入圖片描述
雙端隊列底層是一段假象的連續空間,實際是分段連續的,為了維護其“整體連續”以及隨機訪問的假象,落在了deque的迭代器身上,因此deque的迭代器設計就比較復雜,如下圖所示:
在這里插入圖片描述
那deque是如何借助其迭代器維護其假想連續的結構呢?
在這里插入圖片描述

3.2 deque的缺陷

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

4、為什么選擇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的優點,而完美的避開了其缺陷。

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

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

相關文章

docker配置連接harbor私有倉庫

一、前言 以下分為兩種情況說明docker對harbor私有倉庫的訪問配置&#xff0c;一種是harbor使用自建證書配置https&#xff0c;一種是使用公有證書配置https 二、docker配置 harbor使用自建證書的情況 使用自建證書對harbor進行https配置&#xff0c;docker會將該倉庫識別成不…

SDXL使用animateDiff和hotshot-xl進行文生視頻

截至2023.12.8號&#xff0c;目前市面上有兩款適用于SDXL的文生視頻開源工具&#xff0c;分別是AnimateDiff和hotshot-xl。 一、工具下載鏈接 &#xff08;1&#xff09;AnimateDiff的webui版本的git鏈接&#xff1a; GitHub - continue-revolution/sd-webui-animatediff: A…

pytest測試框架介紹(2)

繼續進步一點點&#xff0c;溫故而知新 一、requests 介紹 1、requests 的官方文檔&#xff1a;https://docs.python-requests.org/en/latest/ 2、安裝requests&#xff1a;pip install requests 二、requests請求 1、請求方法&#xff1a;post&#xff0c;get&#xff0c…

Postman獲取token

問題描述 登錄接口中帶有token參數&#xff0c;其他接口需要帶上token才能正確訪問&#xff0c;利用接口查詢用戶信息時手動在headers中更新token信息并不方便。 解決方案 在登錄接口中設置一個名為“token”的環境變量&#xff0c;value為登錄接口跑通之后responseBody中返回…

51單片機的獨立按鍵與矩陣按鍵的使用以及實例分析

IO 的使用–按鍵 本文主要涉及8051單片機的按鍵的使用&#xff0c;包括獨立按鍵與矩陣按鍵。 其中包括實例分析&#xff1a; 獨立按鍵 K1 控制 D1 指示燈亮滅通過數碼管顯示矩陣按鍵 S1-S16 按下后鍵值 0-F 文章目錄 IO 的使用--按鍵一、按鍵消抖二、獨立按鍵獨立按鍵 K1 控制 …

IAR嵌入式解決方案發布全新版本,增強云調試和仿真功能,推動下一代嵌入式軟件開發

通過先進的Arm虛擬硬件集成和Linux系統中增強的基于云的協作&#xff0c;賦能下一代嵌入式軟件開發 瑞典烏普薩拉&#xff0c;2023年12月7日 - 嵌入式開發軟件和服務的全球領導者IAR宣布推出旗艦產品IAR Embedded Workbench for Arm及IAR Build Tools for Arm最新9.50版本。此…

vue2+datav可視化數據大屏(3)

接上一節所說&#xff0c;當我們將接口封裝完了后&#xff0c;我們需要給大屏進行內容填充啦 1,新建組件 &#x1f4d3; 我們在ser-views文件夾下新建9個vue組件&#xff0c;如下圖所示&#xff0c;我給編號為1到9 &#x1f4d3;在組件里寫入內容我是第一塊...一次類推&#x…

AOSP開機動畫調測技術點(基于Android13)

AOSP開機動畫調測技術點(基于Android13) 開機動畫替換 首先&#xff0c;在你的計算機上創建一個名為"bootanimation"的文件夾&#xff0c;并將"part0"、"part1"和"desc.txt"這三個文件復制到該文件夾中。這些文件包含了開機動畫的圖像…

基于深度學習的超分辨率圖像技術一覽

超分辨率(Super-Resolution)即通過硬件或軟件的方法提高原有圖像的分辨率&#xff0c;圖像超分辨率是計算機視覺和圖像處理領域一個非常重要的研究問題&#xff0c;在醫療圖像分析、生物特征識別、視頻監控與安全等實際場景中有著廣泛的應用。 SR取得了顯著進步。一般可以將現有…

【知識分享】SpringBoot自定義bean

在Spring Boot中&#xff0c;可以使用注解和配置來定義自定義的Bean。以下是自定義Bean的詳細講解和代碼示例&#xff1a; 1.使用注解定義自定義Bean&#xff1a; 在你的自定義類上添加Component或其衍生注解&#xff08;如Service、Repository等&#xff09;&#xff0c;將該…

小機器人,電子鎖,牙刷,表類開關,磁閥開關等一些安防直流驅動的選型介紹分析 5V,大電流,小封裝

安防監控是一門被人們日益重視的新興行業&#xff0c;就目前發展來看&#xff0c;應用普及程度越來越廣&#xff0c;科技含量也越來越高&#xff0c;幾乎所有高新科技都可促進其發展&#xff0c;尤其是信息時代的來臨&#xff0c;更為該行業的發展提供契機。其中安防領域最為典…

docker 容器內數據映射到容器外

es 暴露的端口很多 es 十分的耗內存 es 的數據一般需要放置到安全目錄&#xff01;掛載 啟動elasticsearch [rootiZbp1guc0wov85gocdqeaiZ home]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" elasticsearch:…

【力扣】刷題備忘錄-動歸-62. 不同路徑

62. 不同路徑 class Solution { public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m,vector<int>(n,0));// 2D vector的標準寫法 有些麻煩for (int i 0; i < m; i) dp[i][0] 1; // 又忘記寫&#xff1b;了。。。for (int j 0; j < …

Python實現的一個簡單的GAN(生成對抗網絡)例子

一個簡單的GAN&#xff08;生成對抗網絡&#xff09;例子 以下是使用Python實現的一個簡單的GAN&#xff08;生成對抗網絡&#xff09;例子&#xff0c;它可以生成手寫數字圖像 python # Importing libraries import numpy as np import matplotlib.pyplot as plt from tenso…

【Docker】Docker的安裝部署及優化詳解

一、部署20版本的docker docker初期版本是1.13(同一版本,開源) ——》分類型 1.15 - 1.17 過程中分成兩種。 開源社區 docker-ce 企業版 docker-ee 目前 Docker 只能支持 64 位系統。 #關閉防火墻 systemctl stop firewalld.service setenforce 0 1.1 安裝依賴包 yum instal…

Blackmagic Design Fusion Studio 18 – 創意視覺特效的全能工具!

無論您是電影制片人、電視廣告創作者還是視覺特效藝術家&#xff0c;Blackmagic Design Fusion Studio 18 都是您的完美選擇。這款全能視覺特效軟件為您提供了無限的創意可能性&#xff0c;助力您打造令人驚嘆的視覺效果。 Blackmagic Design Fusion Studio 18 的卓越功能&…

【PWN】學習筆記(二)【棧溢出基礎】

目錄 課程教學C語言函數調用棧ret2textPWN工具 課程教學 課程鏈接&#xff1a;https://www.bilibili.com/video/BV1854y1y7Ro/?vd_source7b06bd7a9dd90c45c5c9c44d12e7b4e6 課程附件&#xff1a; https://pan.baidu.com/s/1vRCd4bMkqnqqY1nT2uhSYw 提取碼: 5rx6 C語言函數調…

Doocker還原容器啟動命令參數

get_command_4_run_container可以還原docker執行命令, 這是個第三方包&#xff0c;需要先安裝&#xff1a; docker pull cucker/get_command_4_run_container 命令格式&#xff1a; docker run --rm -v /var/run/docker.sock:/var/run/docker.sock cucker/get_command_4_run…

MISRA C++ 2023:C和C++測試解決方案實現靜態分析

自動化軟件測試解決方案的全球領導者Parasoft今天宣布&#xff0c;隨著Parasoft C/Ctest 2023.2即將發布&#xff0c;全面支持MISRA C 2023。Parasoft針對C和C軟件開發的完全集成測試解決方案計劃于2023年12月發布&#xff0c;可以幫助團隊實現自動化靜態分析和編碼標準合規性&…

git報錯WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

git報錯WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 可能存在的情況是&#xff1a;連接的gitlab服務已經切換物理服務器。除了上述的可能性還可以參考以下 Git Pull FailedWARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! IT IS POSSIBLE THAT SOMEONE IS DOING …