【C++練級之路】【Lv.10】【STL】priority_queue類和反向迭代器的模擬實現



快樂的流暢:個人主頁


個人專欄:《C語言》《數據結構世界》《進擊的C++》

遠方有一堆篝火,在為久候之人燃燒!

文章目錄

  • 一、仿函數
    • 1.1 仿函數的介紹
    • 1.2 仿函數的優勢
  • 二、priority_queue
    • 2.1 push
    • 2.2 pop
    • 2.3 top
    • 2.4 size
    • 2.5 empty
  • 三、反向迭代器
    • 3.1 成員變量與默認成員函數
    • 3.2 operator*
    • 3.3 operator->
    • 3.4 operator++
    • 3.5 operator- -
    • 3.6 relational operators
  • 四、反向迭代器的適用
  • 4.1 vector
    • 4.1.1 rbegin
    • 4.1.2 rend
  • 4.2 list
    • 4.2.1 rbegin
    • 4.2.2 rend
  • 總結

一、仿函數

1.1 仿函數的介紹

仿函數,是一種特殊類型的類,它重載了()運算符,使得這個類的使用看起來像一個函數,因此它又稱為函數對象

具體來說,仿函數就是將函數的特性賦予到類上,使得這個類有了類似函數的行為。

1.2 仿函數的優勢

C++設計仿函數之初,其實就是想替代龐雜難懂的函數指針,將函數指針替換為簡單易懂的仿函數。

這里列舉兩個常用的仿函數——less和greater

template<class T>
struct less
{bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
struct greater
{bool operator()(const T& x, const T& y){return x > y;}
};

二、priority_queue

細節:

  1. priority_queue也是容器適配器,默認容器使用vector
  2. 其底層數據結構是,并且默認情況為大堆
    如果不了解堆,可以先看往期【數據結構】【版本2.0】【樹形深淵】——二叉樹入侵
  3. 為了能方便調整大小堆,增加了仿函數的模板
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
private:Container _con;
};

悄悄說一句:其實容器模板和仿函數模板位置互換,才更加合理!(平時不怎么會換默認容器,但是會經常換仿函數來控制大小堆)

2.1 push

入堆

細節:

  1. 先尾插元素
  2. 再使用向上調整算法
void push(const T& x)
{_con.push_back(x);adjust_up(_con.size() - 1);
}

向上調整算法

細節:

  • 構造一個仿函數模板對象,再利用重載的()運算符進行比較(當然,也可以使用匿名對象)
void adjust_up(int child)
{Compare com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

2.2 pop

出堆

細節:

  1. 先首尾元素互換
  2. 再尾刪元素
  3. 最后使用向下調整算法
void pop()
{swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);
}

向下調整算法

細節:

  • 構造一個仿函數模板對象,再利用重載的()運算符進行比較(當然,也可以使用匿名對象)
void adjust_down(int parent)
{Compare com;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])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}

2.3 top

獲取堆頂元素

const T& top() const
{return _con[0];
}

2.4 size

獲取堆中有效元素個數

size_t size() const
{return _con.size();
}

2.5 empty

判斷堆是否為空

bool empty() const
{return _con.empty();
}

三、反向迭代器

其實,反向迭代器也是一種適配器,它是根據不同容器的正向迭代器,來生成對應的反向迭代器。

同時,反向迭代器追求一種對稱美,rbegin()在end(),rend()在begin()。

3.1 成員變量與默認成員函數

細節:

  1. 仍然使用struct,標明公有屬性
  2. 成員變量是一個正向迭代器
  3. 提供帶參構造函數(其余的默認成員函數不用顯式定義,淺拷貝即可)
template<class Iterator, class Ref, class Ptr>
struct __reverse_iterator
{typedef __reverse_iterator self;Iterator _cur;__reverse_iterator(Iterator it): _cur(it){}
};

3.2 operator*

細節:

  1. 迭代器先自減,再解引用返回
  2. 返回引用,為了區別普通迭代器和const迭代器
Ref operator*()
{Iterator tmp = _cur;return *--tmp;
}

3.3 operator->

細節:

  1. 直接調用operator*(),根據不同容器的數據取地址返回
  2. 返回指針,為了區別普通迭代器和const迭代器
Ptr operator->()
{return &(operator*());
}

3.4 operator++

細節:

  1. 反向迭代器的++,就是正向迭代器的- -
  2. 為了區分前置和后置,后置參數加上int(無實際意義,以示區分)
  3. 前置傳引用返回,后置傳值返回
self& operator++()
{--_cur;return *this;
}self operator++(int)
{Iterator tmp = _cur;--_cur;return tmp;
}

3.5 operator- -

細節:同上

self& operator--()
{++_cur;return *this;
}self operator--(int)
{Iterator tmp = _cur;++_cur;return tmp;
}

3.6 relational operators

bool operator!=(const self& s)
{return _cur != s._cur;
}bool operator==(const self& s)
{return _cur == s._cur;
}

四、反向迭代器的適用

4.1 vector

template<class T>
class vector
{
public:typedef T* iterator;typedef const T* const_iterator;typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;typedef __reverse_iterator<iterator, const T&, const T*> const_reverse_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}//...
}

4.1.1 rbegin

reverse_iterator rbegin()
{return reverse_iterator(end());
}const_reverse_iterator rbegin() const
{return const_reverse_iterator(end());
}

4.1.2 rend

reverse_iterator rend()
{return reverse_iterator(begin());
}const_reverse_iterator rend() const
{return const_reverse_iterator(begin());
}

4.2 list

template<class T>
class list
{
public:typedef __list_node<T> node;typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;typedef __reverse_iterator<iterator, const T&, const T*> const_reverse_iterator;iterator begin(){return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}//...
}

4.2.1 rbegin

reverse_iterator rbegin()
{return reverse_iterator(end());
}const_reverse_iterator rbegin() const
{return const_reverse_iterator(end());
}

4.2.2 rend

reverse_iterator rend()
{return reverse_iterator(begin());
}const_reverse_iterator rend() const
{return const_reverse_iterator(begin());
}

總結

這次學習了仿函數的概念和基本用法,對于升降序、大小堆等轉換具有極大便利。同時實現了新的容器適配器——priority_queue(優先級隊列),實際上就是堆。并且也完美實現了同為適配器的反向迭代器,至此,對于適配器有了更深一步的了解和運用。


真誠點贊,手有余香

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

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

相關文章

【3D Slicer】心臟CT圖像分割操作保姆級教程 Cardiac CT image segmentation

心臟CT圖像分割操作流程指南 1 安裝3D Slicer軟件2 打開文件2.1 從File->Add Data->Choose File2.2 直接拖入 3 進行分割操作4 切片填充 Fill between slices5 第二個例子6 數據保存7 打開保存后的文件 1 安裝3D Slicer軟件 方式二選一 1.官網&#xff1a;3D Slicer 2.百…

JNI方案說明和使用方法介紹

JNI簡介 JNI(Java Native Interface)是Java編程語言中用于實現Java代碼與本地(Native)代碼(通常是C或C++代碼)交互的機制。它允許Java應用程序調用本地代碼中的功能,也可以讓本地代碼調用Java類和方法。JNI在Java平臺上實現了Java與其他編程語言的互操作性。(即可互相…

無字母數字rce總結(自增、取反、異或、或、臨時文件上傳)

目錄 自增 取反 異或 或 臨時文件上傳 自增 自 PHP 8.3.0 起&#xff0c;此功能已軟棄用 在 PHP 中&#xff0c;可以遞增非數字字符串。該字符串必須是字母數字 ASCII 字符串。當到達字母 Z 且遞增到下個字母時&#xff0c;將進位到左側值。例如&#xff0c;$a Z; $a;將…

C++知識點總結(23):高級模擬算法

高級模擬算法例題 一、P5661 公交換乘1. 審題2. 思路3. 參考答案 二、P1003 鋪地毯1. 審題2. 參考答案 三、P1071 潛伏者1. 審題2. 思路3. 參考答案 一、P5661 公交換乘 1. 審題 2. 思路 總花費中&#xff0c;地鐵是必須花費的&#xff0c;公交車可能不花錢&#xff08;坐地…

使用VisualDL進行模型訓練和數據可視化

文章目錄 使用VisualDL進行模型訓練和數據可視化1. 環境準備1.1 安裝VisualDL1.2 設置VisualDL 2. 寫入數據并可視化2.1 檢查訓練數據2.2 跟蹤模型訓練2.3 評估模型訓練效果 3. 啟動VisualDL服務4. 總結 使用VisualDL進行模型訓練和數據可視化 VisualDL是飛槳提供的一個可視化…

Java中的Object類詳解

Java中的Object類詳解 1. equals(Object obj)2. hashCode()3. toString()4.getClass()5.notify() 和 notifyAll()6. wait() 和 wait(long timeout)7. clone()8.finalize() Java中的 Object 類是所有類的父類&#xff0c;可以被所有Java類繼承并使用。下面先看下源碼&#xff1a…

google最新大語言模型gemma本地化部署

Gemma是google推出的新一代大語言模型&#xff0c;構建目標是本地化、開源、高性能。 與同類大語言模型對比&#xff0c;它不僅對硬件的依賴更小&#xff0c;性能卻更高。關鍵是完全開源&#xff0c;使得對模型在具有行業特性的場景中&#xff0c;有了高度定制的能力。 Gemma模…

革新商務數據體驗:引領市場的API商品數據接口

在當今商業環境中&#xff0c;革新商務數據體驗對于維持競爭優勢至關重要。API商品數據接口在這一轉型過程中扮演了核心角色&#xff0c;它不僅為企業提供了實時且全面的數據訪問能力&#xff0c;而且還極大地增強了數據的可操作性和決策支持功能。以下是API商品數據接口如何細…

面試數據庫篇(mysql)- 12分庫分表

拆分策略 垂直分庫 垂直分庫:以表為依據,根據業務將不同表拆分到不同庫中。 特點: 按業務對數據分級管理、維護、監控、擴展在高并發下,提高磁盤IO和數據量連接數垂直分表:以字段為依據,根據字段屬性將不同字段拆分到不同表中。 特點: 1,冷熱數據分離 2,減少IO過渡爭…

C語言入門到精通之練習42:畫圖,學用圓畫圓形。

題目&#xff1a;畫圖&#xff0c;學用圓畫圓形。 程序分析&#xff1a;無。 實例 #include <graphics.h> //VC6.0中是不能運行的&#xff0c;要在Turbo2.0/3.0中 int main() { int driver,mode,i; float j1,k1; driverVGA; modeVGAHI; initgraph(&d…

【Micropython基礎】TCP客戶端與服務器

文章目錄 前言一、連接Wifi1.1 創建STA接口1.2 激活wifi接口1.3 連接WIFI1.4 判斷WIFI是否連接1.5 連接WIFI總體代碼 二、創建TCP 客戶端2.1 創建套接字2.2 設置TCP服務器的ip地址和端口2.3 連接TCP服務器2.3 發送數據2.4 接收數據2.5 斷開連接2.6 示例代碼 三、TCP服務器的創建…

批量二維碼的教程和優勢:拓寬應用領域,提升效率與創新

隨著二維碼技術的不斷發展&#xff0c;批量二維碼在多個領域展現出了顯著的優勢&#xff0c;為商業和行業帶來了更多便捷和創新。以下是批量二維碼的一些顯著優勢&#xff1a; 1. 高效快速生成&#xff1a; 批量二維碼一次性生成多個二維碼&#xff0c;相較于逐個生成的方式&…

Linux之進程信號

目錄 一、概念引入 1、生活中的信號 2、Linux中的信號 二、信號處理常見方式 三、信號的產生 1、鍵盤產生信號 2、系統調用接口產生信號 3、軟件條件產生信號 4、硬件異常產生信號 四、信號的保存 相關概念 信號保存——三個數據結構 信號集——sigset_t 信號集操…

超簡單的chatgpt-next-web部署教程!

隨著AI的應用變廣&#xff0c;各類AI程序已逐漸普及&#xff0c;尤其是在一些日常辦公、學習等與撰寫/翻譯文稿密切相關的場景&#xff0c;大家都希望找到一個適合自己的穩定可靠的ChatGPT軟件來使用。 ChatGPT-Next-Web就是一個很好的選擇。它是一個Github上超人氣的免費開源…

Docker基礎教程 - 1 Docker簡介

更好的閱讀體驗&#xff1a;點這里 &#xff08; www.doubibiji.com &#xff09; 1 Docker簡介 Docker是一個強大的容器化平臺&#xff0c;讓你能夠更輕松地構建、部署和運行應用程序。 下面我們來學習 Docker。 1.1 Docker是什么 1 現在遇到的問題 每次部署一臺服務器&…

CSS 入門指南(一)CSS 概述

CSS 概述 CSS 介紹 CSS&#xff08;Cascading Style Sheets&#xff09;通常稱為 CSS 樣式或層疊樣式表&#xff0c;是一種用來為結構化文檔&#xff08;如 HTML 文檔或 XML 應用&#xff09;添加樣式&#xff08;字體、間距和顏色等&#xff09;以及版面的布局等外觀顯示樣式…

《MySQL數據庫》day1

文章目錄 1.名詞解釋2.如何啟動mysql數據庫3.mysql常用命令4.數據庫當中最基本的單元是表&#xff1a;table5.關于SQL語句的分類6.簡單查詢7.條件查詢8.排序9.數據處理函數單行處理函數常見的有哪些&#xff1f; 10.分組函數&#xff08;多行處理函數&#xff09; 1.名詞解釋 …

VUE2與VUE3之間的主要區別

當談到 Vue.js 的版本時&#xff0c;Vue 2 和 Vue 3 是最常被提及的兩個版本。下面是 Vue 2 和 Vue 3 之間的一些主要區別&#xff1a; 1. 性能提升&#xff1a; Vue 3 在底層核心重寫了響應式系統&#xff0c;采用了 Proxy 對象&#xff0c;大幅提高了性能。Vue 3 還引入了靜…

徹底解決華為手機安裝谷歌框架后出現未認證的彈窗問題

引言 本人使用華為手機通過B站等平臺學習如何安裝谷歌框架與商店后&#xff0c;發現安裝谷歌框架后出現未認證的彈窗問題少有解決辦法&#xff0c;而且容易復發&#xff0c;在借鑒相關視頻后找到解決辦法&#xff0c;但視頻中的華谷框架需要付費才能使用&#xff0c;本文將提出…

spring注解驅動系列--自動裝配

Spring利用依賴注入&#xff08;DI&#xff09;&#xff0c;完成對IOC容器中中各個組件的依賴關系賦值&#xff1b;依賴注入是spring ioc的具體體現&#xff0c;主要是通過各種注解進行屬性的自動注入。 一、Autowired&#xff1a;自動注入 一、注解介紹 1、默認優先按照類型去…