優先級隊列(堆二叉樹)底層的實現:

我們繼續來看我們的優先級隊列:

優先級隊列我們說過,他也是一個容器適配器,要依賴我們的容器來存儲數據;

他的第二個參數就是我們的容器,這個容器的默認的缺省值是vector,然后他的第三個參數,我們上節講到,他的top和pop接口都是按照優先級的順序來進行去取的,然后我們的優先級順序默認的是大的優先級比較高,這里有一個比較坑的點,那就是我們如果想讓大的數據優先級高的話,我們可以直接不傳,他的默認的缺省值就是大的優先級高,這個缺省值就是less,然后我們如果想讓小的數據的優先級高的話,我們就傳greater,是的,這里就是剛好相反的。

優先級隊列的實現:

我們來實現我們的優先級隊列的底層,我們看這個push函數,我們的庫里面的插入函數就是push,我們在這里的名字就是push,這個函數表示的其實還是尾插,我們的容器vector里面也是實現了push_back() 函數接口的,我們直接調用;

我們看我們的插入函數的參數,我們這里還是使用了引用來進行,這個東西我們已經說過很多次了。

因為我們不能確定這個模板T到底是什么類型的,他可能是內置類型的,比如int,也可能是其他的自定義的類型,如果是自定義的類型的話,我們的傳值調用就要調用拷貝構造了,如果我們的自定義類型有動態開辟的內存的時候,我們調用拷貝構造就要給這個臨時的變量開辟一段內存空間,深拷貝就比較麻煩。我們這里就選擇傳引用來進行,就不需要調用拷貝構造了。

我們來接著看:

由于堆具有高效維護最大或最小元素的特性,它是實現優先級隊列的一種非常合適的數據結構。

我們的堆刪除數據也是刪除棧頂的數據,優先級最高的進行刪除。(優先級隊列也是先刪除優先級高的)。

優先級隊列的實現都是基于堆的。(我們的這個優先級隊列就是我們的堆二叉樹);

push函數的實現:

Adjustup函數的實現:

當我們的優先級隊列(堆)入數據的時候,這個數據的插入有可能會破壞我們的優先級隊列(堆)自身的結構,如果插入數據以后,我們的大堆的結構被改變,我們就要進行向上調整。

上面的這個數據的插入沒有改變我們的堆的類型,他還是大堆,我們就不進行調整了;

當我們再給他插入一個數據的時候,我們這時候的大堆就不成型了,我們就要進行調整,我們把插入的數據找出來,然后我們求出他的parent結點,然后比較大小,如果child比parent大的時候,我們就交換數據,然后不斷比較:

為什么我們要實現向上調整呢?

一般我們入數據的時候,我們就會用到向上調整。

我們看我們的push函數:

我們插入一個數據以后,我們一般都是插入到最后一個位置,然后我們對這個位置進行向上調整。

我們這里是size()-1,因為我們的堆二叉樹,我們的第一個數據是從下標0開始的。

pop函數的實現:

我們實現我們的刪除函數,想一下我們之前實現堆的時候的刪除數據是怎么刪除的:

我們交換堆頂和最后一個數據,然后把最后一個數據刪除。這時候我們進行一個向下調整,這時候除了第一個堆頂的數據,其他的位置的數據都是有序的滿足堆的要求。(這個也剛好滿足向下調整的算法的條件)。

然后左右兩個堆都是有序的,我們就比較現在堆頂(10)的左右孩子,因為是大堆,我們就選出比較大的數據,然后我們的堆頂和這個位置進行交換。當然,比較完后我們的這棵發生交換的子樹還要和下面的孩子進行比較,直到最后合適。????????

Adjustdown向下調整的實現:

pop函數:

我們的向下調整的前體就是我們是pop數據的時候,我們會需要這個。

綜上所述:

向上調整的前提是向堆中插入新元素,向下調整的前提是從堆中刪除堆頂元素。

仿函數:

我們的仿函數是一個類

在 C++ 里,仿函數是重載了函數調用運算符?()?的類或結構體的對象。這意味著這些對象能夠像函數一樣被調用。

這個就是我們的仿函數,重載了()。

這個類的對象可以像函數一樣的去使用,這個類就是我們的仿函數。

我們來看一個仿函數:

我們在我們的優先級隊列里面的時候,我們的模板參數的第三個參數就是我們的仿函數,我們的仿函數也是一個類:

這個就是我們的仿函數。? 這個是less,我們重載的 () 是小于的類型。

這個是我們的greater,我們重載的 () 是大于的類型。

我們這里實現的和我們的庫里面的有所不同,我們的庫里面的,和我們的這里的相反,庫里面的gerater表示小于,less表示大于。

然后當我們的這個大模板下的函數想要使用比較的時候,我們就可以使用仿函數,我們看下面的向下調整的方法,我們里面的條件比較如果是小于的話,我們就可以直接調用仿函數,看他是不是滿足小于的,如果是滿足小于的,返回1,我們的if條件成立。

當然,使用的前提也是,我們要先使用這個類來實例化出一個對象。

我們的compare是我們的仿函數,我們實例化出一個對象com,然后我們的這個類的對象我們可以直接的當作一個函數去使用。

我們這里調用仿函數可以是實例化出一個對象然后我們調用,這個有名調用是可以的,我們也可以是進行匿名調用。

上面的就是有名調用,匿名調用的話,我們就不實例化出對象,然后把圖中的com替換成less<int>。

我們接著看:

我們看這個,我們說我們push的話,我們可以傳有名對象,也可以傳匿名對象,我們也可以像我們的圖片中的樣子,我們傳我們要初始化的值,進行一個隱式類型轉換,也會生成一個匿名對象。和我們的上面的屏蔽的那個匿名對象的效果是一樣的。

我們接著來看我們的仿函數:

我們看一下這個代碼,我們的這個優先級隊列,我們的第一個參數為我們的日期類的地址,然后后面的兩個參數不傳,我們的第二個參數的缺省值為vector,第三個參數缺省值為less,然后我們進行打印,但是打印出來的結果不是我們想要的結果。

我們這次的模板T不是int,是我們的日期類的指針,我們進行push尾插,然后我們的new的返回值是我們的開辟的內存的指針,我們把指針插入到我們的數組里面,然后比較的時候,我們比較的就是我們的地址,我們的new開辟的內存的地址是隨機的,所以我們在這里比較出來的結果就是無意義的。

那怎么辦呢?

我們就可以利用我們的仿函數,我們這里的優先級隊列我們的第三個仿函數我們是沒有傳的,所以這時候我們的里面就是缺省值less,這樣的結果就是比較地址的大小,但是我們可以修改我們的仿函數,我們這里的仿函數是不期望使用指針來進行比較的,我們期望的是使用指針解引用后的數據來比較。

之前我們的仿函數:

我們就設置一個新的仿函數來解決我們的問題:

這時候得到的就是我們要的;(按照里面的數據來進行比較)。

還有:

我們看這個代碼,這個代碼我們的優先級隊列傳過去的容器是string,然后我們的后面的兩個函數參數都是缺省值,我們的最后一個參數仿函數就是less。

我們然后尾插三個字符串,然后不斷的取然后pop,這個就是最后的結果,這個就是按照他的大小進行排列的。

但是我們現在不想按照順序的給他進行排列了,我們想按照每個字符串的長度來進行排列;

我們這時候就可以使用仿函數來調整我們的比較邏輯;

我們看,我們自己來實現一個仿函數,來滿足我們的要求,我們比較兩個string的長度。

如果默認的函數不符合我們的邏輯,我們就自己來實現一個仿函數。

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

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

相關文章

GIC驅動程序分析

今天呢&#xff0c;我們就來具體的講一下GIC的驅動源碼啦&#xff0c;這個才是重點來著&#xff0c;我們來看看&#xff1a; GIC中的重要函數和結構體&#xff1a; 沿著中斷的處理流程&#xff0c;GIC涉及這4個重要部分&#xff1a; CPU從異常向量表中調用handle_arch_irq&am…

java操作redis庫,開箱即用

application.yml spring:application:name: demo#Redis相關配置redis:data:# 地址host: localhost# 端口&#xff0c;默認為6379port: 6379# 數據庫索引database: 0# 密碼password:# 連接超時時間timeout: 10slettuce:pool:# 連接池中的最小空閑連接min-idle: 0# 連接池中的最…

Cribl 通過Splunk search collector 來收集數據

今天利用Spliunk search collector 來收集數據啦:還是要先cribl 的官方文檔: Splunk Search Collector | Cribl Docs Splunk Search Collector Cribl Stream supports collecting search results from Splunk queries. The queries can be both simple and complex, as well a…

What Was the “Game Genie“ Cheat Device, and How Did It Work?

什么是“Game Genie”作弊裝置&#xff0c;它是如何工作的&#xff1f; First released in 1991, the Game Genie let players enter special codes that made video games easier or unlocked other functions. Nintendo didnt like it, but many gamers loved it. Heres wha…

位運算題目:連接連續二進制數字

文章目錄 題目標題和出處難度題目描述要求示例數據范圍 解法思路和算法代碼復雜度分析 題目 標題和出處 標題&#xff1a;連接連續二進制數字 出處&#xff1a;1680. 連接連續二進制數字 難度 5 級 題目描述 要求 給定一個整數 n \texttt{n} n&#xff0c;將 1 \text…

第十六屆藍橋杯Java b組(試題C:電池分組)

問題描述&#xff1a; 輸入格式&#xff1a; 輸出格式&#xff1a; 樣例輸入&#xff1a; 2 3 1 2 3 4 1 2 3 4 樣例輸出: YES NO 說明/提示 評測用例規模與約定 對于 30% 的評測用例&#xff0c;1≤T≤10&#xff0c;2≤N≤100&#xff0c;1≤Ai?≤10^3。對于 100…

63. 評論日記

2025年4月14日18:53:30 雷軍這次是真的累了_嗶哩嗶哩_bilibili

電商中的訂單支付(內網穿透)

支付頁面 接口文檔 Operation(summary"獲取訂單信息") GetMapping("auth/{orderId}") public Reuslt<OrderInfo> getOrderInfo(Parameter(name"orderId",description"訂單id",requiredtrue) PathVaariable Long orderId){OrderI…

MySQL表的使用(4)

首先回顧一下之前所學的增刪查改&#xff0c;這些覆蓋了平時使用的80% 我們上節課中學習到了MySQL的約束 其中Primary key 是主鍵約束&#xff0c;我們今天要學習的是外鍵約束 插入一個表 外鍵約束 父表 子表 這條記錄中classid為5時候&#xff0c;不能插入&#xff1b; 刪除…

Kotlin作用域函數

在 Kotlin 中&#xff0c;.apply 是一個 作用域函數&#xff08;Scope Function&#xff09;&#xff0c;它允許你在一個對象的上下文中執行代碼塊&#xff0c;并返回該對象本身。它的設計目的是為了 對象初始化 或 鏈式調用 時保持代碼的簡潔性和可讀性。 // 不使用 apply va…

C#集合List<T>與HashSet<T>的區別

在C#中&#xff0c;List和HashSet都是用于存儲元素的集合&#xff0c;但它們在內部實現、用途、性能特性以及使用場景上存在一些關鍵區別。 內部實現 List&#xff1a;基于數組實現的&#xff0c;可以包含重復的元素&#xff0c;并且元素是按照添加的順序存儲的。 HashSet&…

Python 實現的運籌優化系統數學建模詳解(最大最小化模型)

一、引言 在數學建模的實際應用里&#xff0c;最大最小化模型是一種極為關鍵的優化模型。它的核心目標是找出一組決策變量&#xff0c;讓多個目標函數值里的最大值盡可能小。該模型在諸多領域&#xff0c;如資源分配、選址規劃等&#xff0c;都有廣泛的應用。本文將深入剖析最大…

數據庫的種類及常見類型

一&#xff0c;數據庫的種類 最常見的數據庫類型分為兩種&#xff0c;關系型數據庫和非關系型數據庫。 二&#xff0c;關系型數據庫介紹 生產環境主流的關系型數據庫有 Oracle、SQL Server、MySQL/MariaDB等。 關系型數據庫在存儲數據時實際就是采用的一張二維表&#xff0…

PE文件(十五)綁定導入表

我們在分析Windows自帶的一些程序時&#xff0c;常常發現有的程序&#xff0c;如notepad&#xff0c;他的IAT表在文件加載內存前已經完成綁定&#xff0c;存儲了函數的地址。這樣做可以使得程序是無需修改IAT表而直接啟動&#xff0c;這時程序啟動速度變快。但這種方式只適用于…

計算機網絡分層模型:架構與原理

前言 計算機網絡通過不同的層次結構來實現通信和數據傳輸&#xff0c;這種分層設計不僅使得網絡更加模塊化和靈活&#xff0c;也使得不同類型的通信能夠順利進行。在網絡協議和通信體系中&#xff0c;最廣為人知的分層模型有 OSI模型 和 TCP/IP模型。這兩種模型分別定義了計算…

Ollama模型顯存管理機制解析與Flask部署方案對比

一、Ollama顯存釋放機制 Ollama部署模型后&#xff0c;顯存占用分為兩種情況&#xff1a; 首次調用后短暫閑置&#xff08;約5分鐘內&#xff09;&#xff1a; ? 釋放KV Cache等中間計算數據&#xff08;約回收30%-50%顯存&#xff09;。 ? 模型權重仍保留在顯存中&#xf…

KWDB創作者計劃—KWDB技術重構:重新定義數據與知識的神經符號革命

引言&#xff1a;數據洪流中的范式危機 在AI算力突破千卡集群、大模型參數量級邁向萬億的時代&#xff0c;傳統數據庫系統正面臨前所未有的范式危機。當GPT-4展現出跨領域推理能力&#xff0c;AlphaFold3突破蛋白質預測精度時&#xff0c;數據存儲系統卻仍在沿用基于關系代數的…

Unified Modeling Language,統一建模語言

UML&#xff08;Unified Modeling Language&#xff0c;統一建模語言&#xff09;是一種標準化的圖形化建模語言&#xff0c;用于可視化、規范和文檔化軟件系統的設計。UML 提供了一套通用的符號和規則&#xff0c;幫助開發者、架構師和團隊成員更好地理解和溝通軟件系統的結構…

IO模式精講總結

一、IO模型概述 Java中的IO模型主要分為BIO&#xff08;同步阻塞IO&#xff09;、NIO&#xff08;同步非阻塞IO&#xff09;和AIO&#xff08;異步非阻塞IO&#xff09;三種。它們分別適用于不同的業務場景&#xff0c;理解其核心機制對高性能網絡編程至關重要。 二、BIO&…

使用pybind11開發c++擴展模塊輸出到控制臺的中文信息顯示亂碼的問題

使用pybind11開發供Python項目使用的C++擴展模塊時,如果在擴展模塊的C++代碼中向控制臺輸出的信息中包含中文,python程序的控制臺很容易出現亂碼。以如下C++擴展框架代碼為例(這是對上一篇文章簡明使用pybind11開發pythonc+擴展模塊教程-CSDN博客中的C++擴展框架代碼進行少量…