C++ set map 詳解

文章目錄

  • 1. 容器
  • 2. set和multiset
    • 2.1 set
      • 2.1.1 構造函數
      • 2.1.2 insert和erase
        • 2.1.2.1 insert
        • 2.1.2.2 erase
      • 2.1.3 查找和訪問
        • 2.1.3.1 set迭代器相關
        • 2.1.3.2 find && count
        • 2.1.3.3 范圍查找
    • 2.2 multiset
      • 2.2.1 insert和erase
      • 2.2.2 find和count
    • 2.3 set和multiset的在算法題中的應用
  • 3. map和multimap
    • 3.1 pair介紹
    • 3.2 map
      • 3.2.1 構造函數
      • 3.2.2 insert和erase
      • 3.2.3 find和count
      • 3.2.4 operator[] 和 at
    • 3.3 multimap

1. 容器

在C++的stl中,容器分為序列式容器和關聯式容器。

對于序列式容器而言,容器的邏輯結構是線性的,相鄰兩個位置的數據之間,沒有較為緊密的聯系,因此通常是可以交換的。對于這類容器的數據訪問,一般都是通過數據存儲的位置進行訪問,最典型的例子,如vector

對于關聯式容器,容器的邏輯結構是非線性的,相鄰兩個位置的數據之間,是有緊密的聯系,通常是不可以交換的,一旦交換,便會破壞整個容器的結構。像map和set,就是關聯式容器的代表,這類容器中數據的訪問,一般都是借助于key,即鍵值來進行訪問的。

2. set和multiset

2.1 set

set的底層是不支持鍵值冗余的二叉搜索樹,存儲的是key,而非key-value
以下,我們介紹使用set容器時,幾個非常重要的接口。

2.1.1 構造函數

set的構造函數,有三個是比較重要的。

一個是默認構造。

在這里插入圖片描述
默認構造中,關于內存池的形參一般不用在意,除非有別的內存池可以供你調用。
set中的仿函數需要注意,默認的仿函數進行的是小于的比較,因此,默認對整個set容器的遍歷,是依據鍵值得到的升序。如果想要得到降序,可以傳入一個進行大于比較的仿函數。

一個是使用迭代器進行構造。

在這里插入圖片描述

還有一個是在C++11中引入的,使用初始化列表這種容器進行構造。

在這里插入圖片描述

2.1.2 insert和erase

2.1.2.1 insert

在set中,我們使用insert來進行鍵值的插入。

較為常用的主要是三個:直接插入鍵值的,插入迭代器區間的,插入初始化列表的。

直接插入鍵值的:

在這里插入圖片描述
我們主要看第一個左值引用,第二個右值引用暫不做討論。
這個函數重載就是直接插入鍵值,比較特殊的是它的返回值,返回的是一個pair類型。

在這個pair類型中,有兩個成員,第一個成員是set的迭代器,第二個成員是bool型的變量。

由于set是不允許鍵值冗余的二叉搜索樹,因此set是存在插入失敗的情況。在插入成功時,pair中包含插入位置對應的迭代器,以及一個true;插入失敗時,返回二叉搜索樹中某個已存在key值的迭代器(此key值與所要插入的key值相同),以及一個false。

其余的兩種形式:

在這里插入圖片描述

2.1.2.2 erase

在這里插入圖片描述
erase有三種刪除形式,其中前兩種使用得最多。

iterator erase(const_iterator position):這是利用迭代器進行刪除,刪除的是迭代器所對應的key,返回值也是一個迭代器——一般是返回刪除元素的后一個迭代器,但如果刪除的元素后面沒有元素,那就返回set.end()

size_type erase (const value_type& val): 這是利用鍵值去刪除。在刪除前,先要找到鍵值對應的具體位置,然后再刪除。這個返回值很特殊,是刪除的數據個數。這讓人有點疑惑,set既然是不支持冗余的,那么刪除的數據個數最多只是1,設計這樣的返回值感覺沒什么用——實際上,這是在設計上與multiset進行一個統一,對于multiset,這個返回值是有意義的。

iterator erase(const_iterator first,const_iterator last):刪除一段迭代器區間。

2.1.3 查找和訪問

2.1.3.1 set迭代器相關

set的迭代器使用和其它容器一樣,這里不做贅述。

在這里插入圖片描述
需要注意的是,雖然set中也區分了const迭代器和非const迭代器,但是無論是哪種迭代器,都是不能對set中的鍵值進行修改,因為一旦修改,就很可能破壞整棵二叉搜索樹的結構。

在這里插入圖片描述

2.1.3.2 find && count

在這里插入圖片描述
利用鍵值進行查找,返回相應位置的迭代器,對應的有const迭代器和非const迭代器兩個版本。

在這里插入圖片描述
count是去查找set中相應鍵值的元素個數,這個在set中不是0,就是1,最主要還是在multiset中的使用,不過在設計時,考慮到set和multiset的協同,因此set中也有這個函數。

2.1.3.3 范圍查找

在這里插入圖片描述
范圍查找lower_bound和upper_bound配套使用

在這里插入圖片描述

在這里插入圖片描述

對于lower_bound,返回的是整棵二叉搜索樹中大于或等于傳入val的第一個數據的迭代器;對于upper_bound,返回的是整棵二叉搜索樹中大于傳入val的第一個數據的迭代器(這里之所以是大于val,緣于迭代器的使用規則,因為迭代器遍歷的循環條件總是!= 某個迭代器)。如果這樣的數據不存在,那么這兩個函數都是返回set.end()

除了上述的用于查找某個范圍的兩個函數,還有一個用于查找相同鍵值范圍的函數,這個函數在set中沒有啥意義,在multiset中才比較有用。

在這里插入圖片描述
這個equal_range函數返回的是一個pair類型,存儲對應某個范圍的左右兩個邊界的迭代器,注意,右迭代器對應這個范圍之后的第一個元素(或是set.end())。如果key值不存在,則pair中的兩個成員變量均為set.end()。

2.2 multiset

相較于set,multiset是支持鍵值冗余的搜素二叉樹。
multiset整體的成員函數于set相類似,不過由于其支持鍵值冗余的特性,在部分函數上會有所差別。

2.2.1 insert和erase

在這里插入圖片描述
對于insert,由于multiset允許鍵值冗余,所以不存在插入失敗的情況,因此直接返回插入位置對應的迭代器即可。

在這里插入圖片描述
對于erase,如果使用的是迭代器版本,那么就是將相應位置的元素清除;如果使用傳val值的版本,則會將multiset中,所有等于該鍵值的數據全部刪除,并返回刪除的數據個數。

2.2.2 find和count

在這里插入圖片描述
multiset中,存在鍵值冗余的情況,那么這個find,究竟是查找哪一個數據呢?
find函數默認查找的是整棵二叉搜索樹的中序遍歷中的鍵值與val相等的第一個數。

在這里插入圖片描述
count函數即返回整棵二叉搜索樹中,與val相等的鍵值的個數。

2.3 set和multiset的在算法題中的應用

set是非鍵值冗余的二叉搜索樹,而二叉搜索數的中序遍歷又是有序的,所以,我們如果要對一系列數據進行去重+排序處理,那么就可以將這些數據放至set容器中,否則就需要使用算法庫中的sort+unique。

multiset是鍵值冗余的二叉搜索樹,如果僅需要實現排序功能,而不需去重,可將數據放至multiset中。

3. map和multimap

map和multimap,底層都是key-value的二叉搜索樹,map允許鍵值冗余,multimap不允許鍵值冗余。由于key-value需要存儲兩個數,所以map和multimap底層存放的數據類型是pair,默認pair類型中的第一個成員是key,第二個成員是value。

3.1 pair介紹

pair是用于存儲成對的,并且往往有關聯的兩個數據,分別存儲到pair的first成員和second成員中,這兩個成員是允許類外直接訪問的。

pair中,最重要的便是如何去構造出一個pair對象,以下介紹幾種常用的方法。

在這里插入圖片描述

pair類型的對象也可以進行大小的比較,重載了相關的運算符。

pair類型對象的比較,先比較成員first,再比較成員second。

  • 相等比較:兩個成員都相等,則相等。
  • 大于比較:誰first大,誰就大;first一樣大,再比較second,誰second大,誰就大。
  • 小于比較:與大于比較邏輯相同,比大轉為比小即可。
  • 不等于比較:兩個成員有一個不相等,便不相等。

3.2 map

3.2.1 構造函數

map的常用構造與set類似,默認構造、拷貝構造和使用一段迭代器區間進行構造。

需要注意的是,由于map的底層數據是pair類型的,因此使用一段迭代器區間進行構造時,迭代器指向的一定要是pair類的對象。

3.2.2 insert和erase

map的insert需要插入一個pair對象。

在這里插入圖片描述
最常見的插入還是單元素的插入,這種插入通常習慣以下兩種寫法:

在這里插入圖片描述

map的erase:

在這里插入圖片描述
size_type erase(const key_type& k) : map中的erase是按照key值來刪除,而非value。

3.2.3 find和count

在這里插入圖片描述
在這里插入圖片描述
均是按照鍵值key來進行查找和統計

3.2.4 operator[] 和 at

方括號在map中的重載,是map中非常重要的一個成員函數,功能也較為復雜。

在這里插入圖片描述
operator[ ]的重載,需要傳一個key值(key_type)進去,返回的是key值相應的value值的引用(mapped_type)。

但實際上,這個重載函數遠沒有看上去那么簡單。這個函數的使用,要分為兩種情況:

  • 相應的key值存在。此時返回key值相應的val值的引用。
  • 相應的key值不存在。此時并不會查找失敗,這個函數會調用insert向map中再插入一個pair對象,這個pair對象的key值是傳入的key值,value值是利用map中的value類型構造出的匿名對象,然后函數再返回這個value值。

實質上,在相應的key值存在時,函數也會調用insert,只不過會插入失敗,不過由于即便插入失敗,insert也會返回相應key值對應的迭代器(返回是pair類型,迭代器為其第一個成員),因此可以正常返回相應value值的引用。

以下是stl庫中,map容器中operator[ ]函數的實現:

mapped_type& operator[] (const key_type& k)
{pair<iterator, bool> ret = insert({ k, mapped_type() });iterator it = ret.first;return it->second;
}

at與operator[ ]類似,傳key值,返回value值,只不過at只能用于已存在的key值查找,不能用于插入不存在的key值,當輸入一個不存在的key值時,at函數會拋異常。

在這里插入圖片描述
以下舉一個使用operator[ ]進行次數統計的典型例子:

在這里插入圖片描述
在main函數中調用,相應的輸出為:

在這里插入圖片描述

3.3 multimap

與map相比較,multimap 是支持鍵值冗余的key-value二叉搜索樹。

multimap與map的差別,同multiset與set的差異相類似,此處不再贅述。

有一點需要注意,map是不支持鍵值冗余,但是value值是可以相同的,只要相應的key值不同即可;而multimap對于key和value則都是沒有限制的。

另外,在multimap中沒有了operator[ ]和at這兩個成員函數,最主要的原因還是在于鍵值冗余,因此會無法解決到底返回哪個value值的問題。

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

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

相關文章

Unity網絡開發基礎 (2) 網絡協議基礎

本文章不作任何商業用途 僅作學習與交流 部分圖片來自Unity唐老師 目錄 1.虛擬模型 2.實際模型 TCP/IP 3.傳輸層協議 TCP/UDP TCP 協議詳解 1. 核心機制 2. 頭部格式&#xff08;20 字節最小&#xff09; UDP 協議詳解 1. 核心特點 2. 頭部格式&#xff08;固定 8 字節…

HTML label 標簽使用

點擊 <label> 標簽通常會使與之關聯的表單控件獲得焦點或被激活。 通過正確使用 <label> 標簽&#xff0c;可以使表單更加友好和易于使用&#xff0c;同時提高整體的可訪問性。 基本用法 <label> 標簽通過 for 屬性與 id 為 username 的 <input> 元素…

JDBC、MyBatis 、MyBatis-Plus面試總結(一)

以下為你整理了一些 MyBatis 和 MyBatis-Plus 中 mapper.xml 相關的常見面試問題及答案&#xff1a; 基礎概念類 問題 1&#xff1a;什么是 mapper.xml 文件&#xff0c;它在 MyBatis 中有什么作用&#xff1f; 答案&#xff1a;mapper.xml 文件是 MyBatis 中用于定義 SQL 語…

GCC RISCV 后端 -- GCC Passes 注釋

在前面文章提到&#xff0c;當GCC 前端完成對C源代碼解析完成后&#xff0c;就會使用 處理過程&#xff08;Passes&#xff09;機制&#xff0c;通過一系列的處理過程&#xff0c;將 GENERIC IR 表示的C程序 轉步轉換成 目標機器的匯編語言。過程描述如下圖所示&#xff1a; 此…

基于Python實現的智能旅游推薦系統(Django)

基于Python實現的智能旅游推薦系統(Django) 開發語言:Python 數據庫&#xff1a;MySQL所用到的知識&#xff1a;Django框架工具&#xff1a;pycharm、Navicat 系統功能實現 總體設計 系統實現 系統首頁模塊 統首頁頁面主要包括首頁&#xff0c;旅游資訊&#xff0c;景點信息…

鴻蒙全棧開發 D2

課程目標 掌握ArkTS基礎語法與核心概念理解聲明式UI開發范式能獨立開發簡單鴻蒙應用組件建立規范的代碼編寫習慣 第一部分&#xff1a;初識ArkTS 1.1 語言全景認知 #mermaid-svg-V5mnjQN3DAHkfoBo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size…

【YashanDB認證】yashandb23.3.1 個人版單機部署安裝實踐

YCA報名鏈接如下: YashanDB|崖山數據庫系統YashanDB學習中心-YCA認證詳情 目前免費 主要參考文檔&#xff1a; 單機&#xff08;主備&#xff09;部署 | YashanDB Doc 另外還參考摩天輪文章&#xff1a; YashanDB 23.2.9.101 企業版安裝步驟搶先看&#xff01; - 墨天輪 …

【藍橋杯】每天一題,理解邏輯(3/90)【Leetcode 快樂數】

閑話系列&#xff1a;每日一題&#xff0c;禿頭有我&#xff0c;Hello&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;,我是IF‘Maxue&#xff0c;歡迎大佬們來參觀我寫的藍橋杯系列&#xff0c;我好久沒有更新博客了&#xff0c;因為up豬我寒假用自己的勞動換了…

爬蟲Incapsula reese84加密案例:Etihad航空

聲明: 該文章為學習使用,嚴禁用于商業用途和非法用途,違者后果自負,由此產生的一切后果均與作者無關 一、找出需要加密的參數 1.js運行 atob(‘aHR0cHM6Ly93d3cuZXRpaGFkLmNvbS96aC1jbi8=’) 拿到網址,F12打開調試工具,隨便搜索航班,切換到network搜索一個時間點可以找…

緩存雪崩 緩存擊穿 緩存穿透

1. redis使用場景-緩存-緩存穿透 在實際開發中&#xff0c;Redis 被廣泛應用于緩存&#xff0c;以提高系統性能和響應速度。然而&#xff0c;在使用緩存時&#xff0c;需要注意一些問題&#xff0c;其中 緩存穿透 是一個常見且需要重點關注的場景。 什么是緩存穿透 ● 緩存穿…

【YOLOv12改進trick】多尺度大核注意力機制MLKA模塊引入YOLOv12,實現多尺度目標檢測漲點,含創新點Python代碼,方便發論文

??改進模塊??:多尺度大核注意力機制(MLKA) ??解決問題??:MLKA模塊結合多尺度、門控機制和空間注意力,顯著增強卷積網絡的模型表示能力。 ??改進優勢??:超分辨的MLKA模塊對小目標和模糊目標漲點很明顯 ??適用場景??:小目標檢測、模糊目標檢測等 ??思路…

better-sqlite3之exec方法

在 better-sqlite3 中&#xff0c;.exec() 方法用于執行包含多個 SQL 語句的字符串。與預編譯語句相比&#xff0c;這種方法性能較差且安全性較低&#xff0c;但有時它是必要的&#xff0c;特別是當你需要從外部文件&#xff08;如 SQL 腳本&#xff09;中執行多個 SQL 語句時。…

電路基礎:【1】PN結二極管制作電橋點亮LED燈

第一章&#xff1a;PN結二極管制作電橋點亮LED燈 文章目錄 第一章&#xff1a;PN結二極管制作電橋點亮LED燈前言一、電路原理二、電路圖與元器件1.電路圖 做實驗總結 前言 在本章中&#xff0c;我們將探討如何通過PN結二極管制作電橋電路&#xff0c;并利用該電路點亮LED燈。L…

XHR請求解密:抓取動態生成數據的方法

在如今動態頁面大行其道的時代&#xff0c;傳統的靜態頁面爬蟲已無法滿足數據采集需求。尤其是在目標網站通過XHR&#xff08;XMLHttpRequest&#xff09;動態加載數據的情況下&#xff0c;如何精準解密XHR請求、捕獲動態生成的數據成為關鍵技術難題。本文將深入剖析XHR請求解密…

機器學習數學基礎:42.AMOS 結構方程模型(SEM)分析的系統流程

該流程圖完整呈現了 AMOS 結構方程模型&#xff08;SEM&#xff09;分析的系統流程&#xff0c;具體步驟及內涵如下&#xff1a; 1. 模型設定 基于理論基礎或研究假設&#xff0c;構建結構方程模型的初始框架&#xff0c;明確潛變量與顯變量的關系、測量模型&#xff08;因子…

以太網通訊

接口開發筆記-WebApi-CSDN博客 以太網常用通訊協議 1、modbus tcp using EasyModbus; using System;class Program {static void Main(string[] args){// 創建Modbus客戶端實例ModbusClient modbusClient new ModbusClient("192.168.1.100"); // IP地址modbusCli…

Arcgis中添加腳本工具箱

文章目錄 準備資料1、打開arcmap2、找到目錄窗口3、復制粘貼工具箱的路徑4、添加或者確認python腳本路徑準備資料 (1)工具箱 (2)python腳本 1、打開arcmap 2、找到目錄窗口 3、復制粘貼工具箱的路徑 4、添加或者確認python腳本路徑 腳本上右鍵屬性(注意:腳本內容和路徑…

TDengine SQL查詢語法

簡介 TDengine 中的查詢 SQL 基本遵循 MYSQL 的查詢語法&#xff0c;大部分查詢都是通過超級表按時間維度進行的各種查詢。 TDengine 時序數據庫以時間為主索引列進行數據組織排序及存儲&#xff0c;同時按存儲塊做了預計算&#xff0c;所以在無普通列過濾的 SQL 查詢語句中聚…

Apache nifi demo 實驗

Apache nifi 是個數據流系統&#xff0c;可以通過配置 自定義的流程來實現數據的轉換。 比如可以配置一個流程&#xff0c;讀取數據庫里的數據&#xff0c;再轉換&#xff0c;最后保存到本地文件。 這樣可以來實現一些數據轉換的操作&#xff0c;而不用特地編寫程序來導入導出。…

javascript一些原生方法記錄

Element.scrollIntoView() Element 接口的 scrollIntoView() 方法會滾動元素的父容器&#xff0c;使被調用 scrollIntoView() 的元素對用戶可見。 structuredClone() 方法 Window 接口的 structuredClone() 方法使用結構化克隆算法將給定的值進行深拷貝。