【C++容器】優先級隊列 仿函數 反向迭代器

優先級隊列,仿函數,反向迭代器

    • 優先級隊列
      • 認識優先級隊列
      • 模擬實現優先級隊列
    • 淺談仿函數
      • 仿函數的大致了解
      • 仿函數的實現
    • 反向迭代器
      • 什么是反向迭代器?
      • 反向迭代器的實現
    • 結語

優先級隊列

認識優先級隊列

優先級隊列(priority_queue)不是隊列。優先級隊列是一種容器適配器,與(stack),隊列(queue)具有類似的功能。

先來了解一下優先級隊列有哪些功能。看下圖:

在這里插入圖片描述

優先級隊列底層是一個(默認是大堆),第二個參數默認給的是vector,不適合list,第三個參數是仿函數函數對象)。

在這里插入圖片描述

模擬實現優先級隊列

大部分成員函數可以通過調用vector的成員函數來實現。

#pragma oncenamespace bit {//目前建堆默認大堆,如果想建小堆怎么辦?template<class T, class Container = vector<T>>class priority_queue {private://不想讓別人知道這兩個函數,可以設置為私有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){Compare com;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child + 1] > _con[child]){++child;}if (com(_con[child], _con[parent])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){//傳過來的迭代器可能不是有序的,所以要排序建堆。while (first != last){push(*first);++first;}}priority_queue()//會調用vector的默認構造函數{}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top() const{return _con[0];}bool empty() const{return _con.empty();}void pop(){//為什么swap不交換swap(_con[0], _con[_con.size() - 1]);//_con.size() - 1;//為什么這個程序不執行?執行了,但是size沒變,只是_con.size() - 1_con.pop_back();AdjustDown(0);}void swap(priority_queue& pq){std::swap(_con, pq._con);}size_t size() const{return _con.size();}private:Container _con;};
}

如果想建小堆,但不增加代碼量的冗余,有辦法嗎?

淺談仿函數

仿函數的大致了解

怎么建小堆?可以增加一個參數函數指針,這個函數來控制大堆還是小堆。但是函數指針聲明比較復雜,有一些聲明很長,導致通用性變差。所以,仿函數就來了。

寫一個類,類中寫相應的方法,這個類作為參數,那么就可以調用該類中的方法了。

仿函數(函數對象)不是函數調用,只是具有函數的功能。

如下代碼是對上面代碼的補充與修改

仿函數的實現

#pragma oncenamespace bit {template<class T, class Container = vector<T>, class Compare = Greater<int>>class priority_queue {private://不想讓別人知道這兩個函數void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[child], _con[parent])){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void AdjustDown(int parent){Compare com;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && com(_con[child + 1], _con[child])){++child;}if (com(_con[child], _con[parent])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){//傳過來的迭代器可能不是有序的,所以要排序建堆。while (first != last){push(*first);++first;}}priority_queue()//會調用默認的構造函數{}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top() const{return _con[0];}bool empty() const{return _con.empty();}void pop(){//為什么swap不交換swap(_con[0], _con[_con.size() - 1]);//_con.size() - 1;//為什么這個程序不執行?執行了,但是size沒變,只是_con.size() - 1_con.pop_back();AdjustDown(0);}void swap(priority_queue& pq){std::swap(_con, pq._con);}size_t size() const{return _con.size();}private:Container _con;};
}
template<class T>
struct Less
{
public:bool operator()(T& x, T& y){return x > y;}
};
template<class T>
struct Greater
{
public:bool operator()(T& x, T& y){return x < y;}
};

仿函數很方便,類中寫許多的函數,資源的管理性不錯,參數就可以只傳一個類,封裝性很強,靈活性很高。

反向迭代器

什么是反向迭代器?

**反向迭代器(reverse_iterator)**就是迭代器的相反。rbegin就是end,rend就是begin。

在這里插入圖片描述

圖中表示的rbegin,rend就是反向迭代器。

那如何實現反向迭代器呢?

反向迭代器的實現

仔細觀察上面那張圖,begin與rbegin,end與rend都是對稱的。

·反向迭代器初始化可以調用正向迭代器的初始化

·反向迭代器++就是正向迭代器 的–,–就是正向迭代器的++。

先來看看庫里面的反向迭代器是如何實現的。

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

反向迭代器中有一個正向迭代器成員。++和–操作沒有問題,都是調用正向迭代器的++和–函數,但是解引用(*)函數中為什么要–?

我們根據如下代碼進行分析:

#include<iostream>
#include<vector>
using namespace std;int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);vector<int>::reverse_iterator rit = v.rbegin();for (rit != v.rend()){cout << *rit << " ";++rit;}cout << endl;
}

在這里插入圖片描述
)rbegin 是由 end 初始化的,所以指向最后一個元素的下一個位置。所以解引用時,rbegin 要到前一個位置,返回前一個位置的元素,rbegin不變,rbegin 和 rend 相等時循環結束。

反向迭代器的實現:

//反向迭代器可以封裝一個正向迭代器,各種操作可以調用正向迭代器的函數
template<class Iterator, class Ref, class Ptr>
class ReverseIterator {
private:Iterator _it;
public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;ReverseIterator()//調用正向迭代器的構造函數{}ReverseIterator(const Iterator& it):_it(it)//調用正向迭代器的拷貝構造函數{}Ref operator*()//解引用指向前一個位置的元素,本身不變。{Iterator tmp = _it;return *(--tmp);}Self& operator++()//調用正向迭代器--函數{--_it;return *this;}Self& operator--()//調用正向迭代器++函數{++_it;return *this;}bool operator!=(const Self& s)//調用正向迭代器的!=函數{return _it != s._it;}
};

結語

優先級隊列(priority_queue)實現較為簡單,與數據結構中的堆很相似。實現優先級隊列與實現棧和隊列的區別是:棧和隊列可以直接復用其他容器的函數,優先級隊列則需要自己加一些東西進去加工,如向下調整,仿函數等。

仿函數替換成函數指針。函數指針很麻煩,寫個函數聲明很長,讀懂也容易繞暈。仿函數就是一個類,類中可以寫許多函數,封裝的很好,使用時很方便。

反向迭代器(reverse_iterator)就是理解解引用(*)的過程,寫起來就是封裝一個正向迭代器。

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

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

相關文章

Doris分區與分桶(八)

接上篇----------Doris 建表示例 Doris 支持兩層的數據劃分。第一層是 Partition&#xff0c;支持 Range 和 List 的劃分方式。第二層是 Bucket&#xff08;Tablet&#xff09;&#xff0c;僅支持 Hash 的劃分方式。 也可以僅使用一層分區。使用一層分區時&#xff0c;只支持…

低成本打造便攜式無線網絡攻防學習環境

1.摘要 一直以來, 無線網絡安全問題與大眾的個人隱私息息相關, 例如: 為了節省流量, 連接到一個看似安全的免費WiFi, 在使用過程中泄露自己的各類密碼信息甚至銀行卡賬號密碼信息。隨著家用智能電器的普及, 家中的各類智能設備連入家里的無線網絡, 卻突然失靈, 甚至無法正常連…

模擬Spring源碼思想,手寫源碼,理解注解

1、BeanDefinition package com.csdn.myspring; import lombok.AllArgsConstructor; import lombok.Data; Data AllArgsConstructor public class BeanDefinition {private String beanName;private Class beanClass; }2、掃描包的工具類MyTools package com.csdn.myspring; im…

@Scheduled注解 定時任務講解

用于在Java Spring框架中定時執行特定任務的注解 Scheduled&#xff0c;它能夠指定方法在特定時間間隔或特定時間點執行。默認參數是cron&#xff0c;cron參數被用來定義一個Cron表達式&#xff0c;它代表了任務執行的時間規則 參數如下 Cron 這是是一種時間表達式&#xff…

【應用程序啟動過程-三種加載控制器的方式-上午內容復習 Objective-C語言】

一、我們先來回憶一下,上午所有內容 1.首先呢,我們先說的是這個“應用程序啟動過程”, 應用程序啟動過程里面,有三方面內容 1)UIApplication對象介紹 2)AppDelegate對象介紹 3)應用程序啟動過程 現在不知道大家對這個應用程序啟動過程有印象嗎, 2.首先,這個UIAp…

MySQL數據庫時間計算的用法

今天給大家分享如何通過MySQL內置函數實現時間的轉換和計算&#xff0c;在工作當中&#xff0c;測試人員經常需要查詢數據庫表的日期時間&#xff0c;但發現開發人員存入數據庫表的形式都是時間戳形式&#xff0c;不利于測試人員查看&#xff0c;測試人員只能利用工具對時間戳進…

【 順序表經典算法—移除元素和合并兩個有序數組】

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 目錄 前言 經典算法OJ題1&#xff1a; 移除元素 解法一、逐個判斷 解法二、雙指針覆蓋 經典算法OJ題2&#xff1a; 合并兩個有序數組 OJ題分為兩個類型&#xff1a; 總結 前言…

MAX/MSP SDK學習07:list傳遞

實現自定義Obejct&#xff0c;要求將傳入的一組數據100后傳出。 #include "ext.h" #include "ext_obex.h" typedef struct _listTrans {t_object ob;void* outLet;t_atom* fArr;long listNum;} t_listTrans;void* listTrans_new(t_symbol* s, long arg…

14.Python 模塊

目錄 1. 使用模塊2. 使用包3. 常用模塊3.1 日期和時間3.2 偽隨機數3.3 摘要算法3.4 JSON 處理3.5 圖像處理 模塊是Python用來組織代碼的一種方法&#xff0c;包是Python用來組織模塊的一種方法。 1. 使用模塊 Python 把能夠相互包含&#xff0c;且有組織的代碼段稱為模塊&…

.NET面試題1

1.什么是C#&#xff1f; C#&#xff08;讀作"C sharp"&#xff09;是一種通用的、面向對象的編程語言&#xff0c;由Microsoft開發。它是一種靜態類型語言&#xff0c;支持強類型檢查和面向對象編程&#xff08;OOP&#xff09;的概念。C#主要用于開發Windows應用程序…

Bug等級劃分

Bug是指在程序或系統中存在的錯誤、缺陷或異常&#xff0c;是由于編碼錯誤、設計問題、邏輯錯誤或其他因素導致的。 常見的Bug分類方法 功能性Bug與軟件的功能有關&#xff0c;軟件無法正常工作、功能與需求不符或功能執行不正確。 用戶界面Bug與軟件的用戶界面有關&#xff…

Unity中Shader雙向反射分布函數BRDF

文章目錄 前言一、渲染方程二、什么是BxDF1、BSSRDF2、BRDF3、BTDF4、BSDF 三、迪士尼原則的BRDF四、迪士尼原則的BRDF的參數五、在Unity中看一下默認Shader的這些參數六、在這里記錄一下使用 Blender 和 SubstancePainter 的流程1、在Blender中導出模型為 .obj 格式2、在Subst…

Android WMS—— Surace管理 (二十)

WMS 負責創建 Surface 以及對 Surface 的擺放工作,之后將 Surface 提交給SurfaceFlinger 進行合并。在 App 層也創建了一個 Surface 對象,但是那個是空對象,用于 WMS 的填充。 一、Surface的創建 首先 APP 層在 ViewRootImpl 的 relayoutWindow() 方法中發起創建任務。 1、…

Go 實現網絡代理

使用 Go 語言開發網絡代理服務可以通過以下步驟完成。這里&#xff0c;我們將使用 golang.org/x/net/proxy 包來創建一個簡單的 SOCKS5 代理服務作為示例。 步驟 1. 安裝 golang.org/x/net/proxy 包 使用以下命令安裝 golang.org/x/net 包&#xff0c;該包包含 proxy 子包&am…

天軟特色因子看板 (2023.11 第12期)

該因子看板跟蹤天軟特色因子A05006(近一月單筆流入流出金額之比(%)&#xff0c;該因子為近一個月單筆流入流出金額之比(%)均值因子&#xff0c;用以刻畫在 市場日內分時成交中流入、流出成交金額的差異性特點&#xff0c;發掘市場主力資金的作用機制。 今日為該因子跟蹤第12期&…

expect腳本在自動化部署中的具體應用案例

#expect腳本在自動化部署中的具體應用 expect腳本是一個非常好的交互式應用腳本&#xff0c;在自動化部署中&#xff0c;可以使用這個腳本來實現全自動的自動化部署。下面是一些具體的應用案例。 場景一&#xff1a;自動安裝mysql 可以使用expect腳本來實現mysql自動安裝&…

Windows平臺Unity下實現camera場景推送RTMP|輕量級RTSP服務|實時錄像

技術背景 我們在對接Unity平臺camera場景采集的時候&#xff0c;除了常規的RTMP推送、錄像外&#xff0c;還有一些開發者&#xff0c;需要能實現輕量級RTSP服務&#xff0c;對外提供個拉流的RTSP URL。 目前我們在Windows平臺Unity下數據源可采集到以下部分&#xff1a; 采集…

@PostConstruct雖好,請勿亂用

1.問題說明 在日常的業務開發中&#xff0c;有時會利用PostConstruct在容器啟動時執行一些任務。例如&#xff1a; PostConstruct public void init(){System.out.println("service 初始化..............."); }一般情況這沒什么問題&#xff0c;但最近一個同事在做…

ui5使用echart

相關的代碼已經發布到github上。 展示下相關的實現功能 1、柱狀圖-1 2、柱狀圖-2 3.折線圖 4.餅狀圖 如何使用&#xff1a; 使用git clone項目到本地 git clone https://github.com/linhuang0405/com.joker.Zechart找到index.html。在vscode里右鍵選擇Open with Live Serve…

1

【任務 1】私有云服務搭建[10 分] 【題目 1】基礎環境配置[0.5 分] 【題目 2】Yum 源配置[0.5 分] 【題目 3】配置無秘鑰 ssh[0.5 分] 【題目 4】基礎安裝[0.5 分] 【題目 5】數據庫安裝與調優[0.5 分] 【題目 6】Keystone 服務安裝與使用[0.5 分] 【題目 7】Glance 安裝與使用…