C++入門小館: STL 之queue和stack

嘿,各位技術潮人!好久不見甚是想念。生活就像一場奇妙冒險,而編程就是那把超酷的萬能鑰匙。此刻,陽光灑在鍵盤上,靈感在指尖跳躍,讓我們拋開一切束縛,給平淡日子加點料,注入滿滿的passion。準備好和我一起沖進代碼的奇幻宇宙了嗎?Let's go!

我的博客:yuanManGan

我的專欄:C++入門小館?C言雅韻集?數據結構漫游記? 閑言碎語小記坊?題山采玉?領略算法真諦

目錄

怎么使用隊列和棧:

隊列和棧的模擬實現:

deque:

priority_queue


先來了解

怎么使用隊列和棧:

這些接口看起來已經很熟悉了。

直接來看看使用吧:

使用就很簡單了。

隊列和棧的模擬實現:

我們先來了解一下適配器:

適配器大家比較熟悉的就是電源適配器,我們的充電器。

queue和stack都是一種容器適配器。

我們用其他類來封裝這兩個容器。

我們回憶一下stack只需要在一方插入和刪除,我們vector和list都能滿足要求,所以我們來簡單來實現一下。

#pragma once
#include<vector>
#include<list>
#include<deque>namespace refrain
{template<class T, class Container = std::deque<T>>class stack{public:T& top() {return _con.back();}const T& top() const{return _con.back();}void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}size_t size() const{return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

deque:

這里的缺省值給的是deque雙端隊列,等會再來講解。

再來回憶一下隊列,它是先進先出,一端入數據一端出數據,我們就拿頭部出數據,尾部入數據,簡單實現如下:

#include<deque>
#include<iostream>
using namespace std;
namespace refrain
{template<class T, class Container = std:: deque<T>>class queue{public:void push(const T& x){_con.push_back(x);}T& front(){return _con.front();}const T& front() const{return _con.front();}T& back(){return _con.back();}const T& back() const{return _con.back();}void pop(){_con.pop_front();}size_t size() const{return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

這里我們有個問題我們的vector不是沒有pop_front嗎,那我們是不是不能用vector來實現隊列呢?的確庫里面他就是用的pop_front,庫里面不想你使用vector來實現,因為vector頭部操作麻煩時間復雜度高,那我們能不能強制實現呢?我們可以使用erase來實現頭部刪除就可以用vector來實現queue了。

這是庫里實現的:

這樣就適用了,但我們一般用deque這個更優秀

接下來就簡單講講deque了:

先來對比一下list和vector的各自的優缺點:

而我們vector的優點就是list的缺點,vector的缺點就是list的優點。

優點:缺點
vector

1.支持下標隨機訪問,

2.CPU高速緩存命中率高

1.頭部或中間位置的插入刪除操作效率低下,因為要挪動數據

2.擴容有一定的成本,存在一定的浪費。比如現在容量為100滿了擴成200只插入了120空間浪費了80空間。

list

1.容易位置的插入和刪除的時間復雜度都是O(1),不需要挪動數據。

2.不存在擴容,按需申請釋放,不浪費空間。

1.不支持下標隨機訪問

2.CPU高速緩存命中率低

這里補充一個知識CPU高速緩存命中率的知識:

cpu想要訪問內存的一個數據,要看這個數據是否在緩存,在就緩存命中,不在就不命中;不命中就先加載到緩存,然后再訪問緩存。

它加載到緩存不是只加載一個數據而是加載一個范圍的數據,因為vector創建的是連續的空間,cpu的高高速緩存就高,而list每次都得先加載到緩存然后再訪問緩存。

接下來就來簡單了解一下deque的底層實現了。?

我們用四個指針封裝deque的迭代器。

我們創建多個buff數組,用first指向buff的第一個位置,last指向最后一個位置。用cur指向當前位置。

再創建一個中控數組map,map里面存儲著指向buff數組的指針,也就是二級指針。

這樣設計有什么好處呢?

當我們迭代器++時

直接++cur,如果cur是最后一個的時候就移動node代碼如下:

庫里面是這樣實現的:?

邏輯是一樣的,但它的細節 處理的更好。

減減也是相同的邏輯,就不實現了。

解引用操作就很簡單了

直接解引用cur。

push_back:

如果push_back時buff沒有慢,就直接cur++,last++。?

當buff已經滿了,我們就得創建一個buff了,讓node++,然后cur指向buff的第二個元素,last指向末尾,first指向第一個元素,如圖。

再來看看push_front

當buff滿了,就創buff,此時我們cur不是指向第一個元素,指向的是最后一個元素,要保持連續性,node--,last,first指向尾和頭。

再頭插一個:

j就直接cur--就行了。

總結一下:

優點:

?????????1.頭尾部插入刪除效率很高

? ? ? ? ?2.下標隨機訪問效率還可以,但不如vector。

缺點:

? ? ? ? ?1.中間位置插入和刪除效率一般。

? ? ? ? ?2.對比vector和list沒有那么極致。(不專一)

?適合做stack和queue的適配器

priority_queue

優先級隊列也不是隊列是堆,堆之前我們用c語言就實現過,我們看看stl庫里面怎樣實現的。

我們之前實現的堆,大家回憶一下,是不是用到了大量的下標訪問?,我們就可以使用vector來當容器適配器。

當我們插入一個數50的時候,這時候還是一個堆,就不進行操作

而當我們插入35的時候:我們要進行向上調整算法。?

?

那我們回憶一下怎么找父親節點呢?

parent = (child - 1)/ 2。

我們就寫一個向下調整算法

如果c語言實現的時候認真學習的應該沒有什么問題。

同樣的刪除堆頂時我們交換堆頂和最后一個位置,然后尾刪,進行向下調整算法

我們找左右孩子怎么找到呢?

左孩子: child = parent * 2 + 1

右孩子:child = parent* 2 + 2

一樣實現的輕而易舉:

?我們就來實現一下堆吧:

template<class T, class Container = std::vector<T>>
class priority_queue
{
public:void push(const T& x){_con.push_back(x);adjustup(_con.size() - 1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjustdown(0);}const T& top() const{return _con[0];}bool empty(){return _con.empty();}//大堆void adjustup(int child){int parent = (child - 1) / 2;while (child > 0){if (_con[child] > _con[parent]){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjustdown(int parent){int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child + 1] > _con[child]){child++;}if (_con[child] > _con[parent]){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}
private:Container _con;
};

?

這里的top就不能實現兩個版本了,因為棧頂的元素不支持修改。?

這里還缺少一個參數是什么呢,這里可以用仿函數來實現:

仿函數

我們可以通過重載( )括號運算符來實現仿函數:

?

我們可以利用這個特性來讓我們選擇能創的是大堆還是小堆,但我們這個有點坑,傳less創建的是小堆,我們只好按它的來哦。

#pragma once
#include<vector>
#include<iostream>namespace refrain
{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 = std::vector<T>, class Compare = less<T>>class priority_queue{public:Compare com;void push(const T& x){_con.push_back(x);adjustup(_con.size() - 1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjustdown(0);}const T& top() const{return _con[0];}bool empty(){return _con.empty();}//大堆void adjustup(int child){int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjustdown(int parent){int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child++;}if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}private:Container _con;};}

?完了over!

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

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

相關文章

ALTER TABLE 刪除DROP表列的報錯: 因為有一個或多個對象訪問此列

目錄 1.問題 2.解決辦法 1.問題 刪除某個列名的時候&#xff0c;提示錯誤因為有一個或多個對象訪問此列 2.解決辦法 2.1 添加或刪除表新列名 將表中的字段設置Default 或 NOT NULL 都會給該字段添加約束&#xff0c;增加了這些約束后&#xff0c;再SQL腳本修改類型、刪除會發生…

python源碼打包為可執行的exe文件

文章目錄 簡單的方式&#xff08;PyInstaller&#xff09;特點步驟安裝 PyInstaller打包腳本得到.exe文件 簡單的方式&#xff08;PyInstaller&#xff09; 特點 支持 Python 3.6打包為單文件&#xff08;–onefile&#xff09;或文件夾形式自動處理依賴項 步驟 安裝 PyIns…

【2025最近Java面試八股】Spring中循環依賴的問題?怎么解決的?

1. 什么是循環依賴&#xff1f; 在Spring框架中&#xff0c;循環依賴是指兩個或多個bean之間相互依賴&#xff0c;形成了一個循環引用的情況。如果不加以處理&#xff0c;這種情況會導致應用程序啟動失敗。導致 Spring 容器無法完成依賴注入。 例如&#xff1a; Service publi…

JimuBI 積木報表 v1.9.5發布,大屏和儀表盤,免費數據可視化

項目介紹 JimuBI (積木報表BI) 是一款免費的數據可視化產品&#xff0c;含大屏和儀表盤、門戶、移動圖表&#xff0c;像搭建積木一樣完全在線設計&#xff01; 大屏采用類word風格&#xff0c;可以隨意拖動組件&#xff0c;想怎么設計怎么設計&#xff0c;可以像百度和阿里一樣…

云原生課程-Docker

一次鏡像&#xff0c;到處運行。 1. Docker詳解&#xff1a; 1.1 Docker簡介&#xff1a; Docker是一個開源的容器化平臺&#xff0c;可以幫助開發者將應用程序和其依賴的環境打包成一個可移植的&#xff0c;可部署的容器。 docker daemon:是一個運行在宿主機&#xff08;DO…

HikariCP 6.3.0 完整配置與 Keepalive 優化指南

HikariCP 6.3.0 完整配置與 Keepalive 優化指南 HikariCP 是一個高性能、輕量級的 JDBC 連接池框架&#xff0c;廣泛應用于 Java 應用&#xff0c;尤其是 Spring Boot 項目。本文檔基于 HikariCP 6.3.0 版本&#xff0c;詳細介紹其功能、配置參數、Keepalive 機制以及優化建議…

基于springboot+vue的攝影師分享交流社區的設計與實現

開發語言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服務器&#xff1a;tomcat7數據庫&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;數據庫工具&#xff1a;Navicat11開發軟件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

ComfyUI for Windwos與 Stable Diffusion WebUI 模型共享修復

#工作記錄 雖然在安裝ComfyUI for Windwos時已經配置過extra_model_paths.yaml 文件&#xff0c;但升級ComfyUI for Windwos到最新版本后發現原先的模型配置失效了&#xff0c;排查后發現&#xff0c;原來是 extra_model_paths.yaml 文件在新版本中被移動到了C盤目錄下&#x…

【最新版】沃德代駕源碼全開源+前端uniapp

一.系統介紹 基于ThinkPHPUniapp開發的代駕軟件。系統源碼全開源&#xff0c;代駕軟件的主要功能包括預約代駕、在線搶單、一鍵定位、在線支付、車主登記和代駕司機實名登記等?。用戶可以通過小程序預約代駕服務&#xff0c;系統會估算代駕價格并推送附近代駕司機供用戶選擇&…

react的 Fiber 節點的鏈表存儲

在React Fiber架構中&#xff0c;Fiber節點的鏈表存儲是一種重要的數據結構組織方式&#xff0c;用于管理和遍歷Fiber節點。以下是關于Fiber節點鏈表存儲的詳細介紹&#xff1a; 鏈表結構 單鏈表&#xff1a;React Fiber節點通過next指針形成單鏈表結構。每個Fiber節點都有一…

Kafka + Kafka-UI

文章目錄 前言&#x1f433; 一、使用純 Kafka Kafka-UI &#xff08;無 Zookeeper&#xff09;Docker 配置&#x1f680; 啟動步驟? 服務啟動后地址&#x1f525; 注意事項&#xff08;使用 Kraft&#xff09;? NestJS Kafka 連接不變&#x1f9e0; 額外補充&#x1f4e6; …

AI聲像融合守護幼兒安全——打罵/異常聲音報警系統的智慧防護

幼兒園是孩子們快樂成長的搖籃&#xff0c;但打罵、哭鬧或尖叫等異常事件可能打破這份寧靜&#xff0c;威脅幼兒的身心安全。打罵/異常聲音報警系統&#xff0c;依托尖端的AI聲像融合技術&#xff0c;結合語音識別、情緒分析與視頻行為檢測&#xff0c;為幼兒園筑起一道智能安全…

Qt網絡數據解析方法總結

在Qt中解析網絡數據通常涉及接收原始字節流&#xff0c;并將其轉換為有意義的應用層數據。以下是詳細步驟和示例&#xff1a; 1. 網絡數據接收 使用QTcpSocket或QUdpSocket接收數據&#xff0c;通過readyRead()信號觸發讀取&#xff1a; // 創建TCP Socket并連接信號 QTcpSo…

unity編輯器的json驗證及格式化

UNITY編輯器的json格式化和驗證工具資源-CSDN文庫https://download.csdn.net/download/qq_38655924/90676188?spm1001.2014.3001.5501 反復去別的網站驗證json太麻煩了 用這個工具能方便點 # Unity JSON工具 這是一個Unity編輯器擴展&#xff0c;用于驗證、格式化和壓縮JSO…

學習筆記:Qlib 量化投資平臺框架 — FIRST STEPS

學習筆記&#xff1a;Qlib 量化投資平臺框架 — FIRST STEPS Qlib 是微軟亞洲研究院開源的一個面向人工智能的量化投資平臺&#xff0c;旨在實現人工智能技術在量化投資中的潛力&#xff0c;賦能研究&#xff0c;并創造價值&#xff0c;從探索想法到實施生產。Qlib 支持多種機器…

操作系統:計算機世界的基石與演進

一、操作系統的本質與核心功能 操作系統如同計算機系統的"總管家"&#xff0c;在硬件與應用之間架起關鍵橋梁。從不同視角觀察&#xff0c;其核心功能呈現多維價值&#xff1a; 硬件視角的雙重使命&#xff1a; 硬件管理者&#xff1a;通過內存管理、進程調度和設…

基于單片機的溫濕度采集系統(論文+源碼)

2.1系統的功能 本系統的研制主要包括以下幾項功能&#xff1a; (1)溫度檢測功能&#xff1a;對所處環境的溫度進行檢測&#xff1b; (2)濕度檢測功能&#xff1a;對所處環境的濕度進行檢測&#xff1b; (3)加熱和制冷功能&#xff1a;可以完成加熱和制冷功能。 (4)加濕和除…

webrtc使用

demo https://www.webrtc-experiment.com/ github開源demo https://github.com/muaz-khan/WebRTC-Experiment.git ws傳遞webrtc信令,本機不需要stun服務器,遠端電腦需要ice服務器建立peer連接 const WebSocket = require(ws); const express =

【數據可視化-25】時尚零售銷售數據集的機器學習可視化分析

?? 博主簡介:曾任某智慧城市類企業算法總監,目前在美國市場的物流公司從事高級算法工程師一職,深耕人工智能領域,精通python數據挖掘、可視化、機器學習等,發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN人工智能領域的優質創作者,提供AI相關的技術咨詢、項目開發和個…

Python Cookbook-6.11 緩存環的實現

任務 你想定義一個固定尺寸的緩存&#xff0c;當它被填滿時&#xff0c;新加入的元素會覆蓋第一個(最老的)元素。這種數據結構在存儲日志和歷史信息時非常有用。 解決方案 當緩存填滿時&#xff0c;本節解決方案及時地修改了緩存對象&#xff0c;使其從未填滿的緩存類變成了…