C++ map和set

C++參考文獻:cplusplus.com - The C++ Resources Network


目錄

一、序列式容器和關聯式容器

二、set系列

(1)set類的介紹

(2)set的構造和迭代器

(3)set的接口

??1.insert?編輯

2.find和erase

3.lower_bound和upper_bound

(4)set和multiset的差異

三、map系列

(1)map類的介紹

(2)pair類型介紹

(3)map的接口

1.insert

2.erase

3.operator[]

(4)multimap和map的差別


一、序列式容器和關聯式容器

前面我們已經接觸過STL中的部分容器如:string、vector、list、deque、array、forward_list等,這些容器統稱為序列式容器,因為邏輯結構為線性序列的數據結構,兩個位置存儲的值之間一般沒有緊密的關聯關系,比如交換一下,他依舊是序列式容器。順序容器中的元素是按他們在容器中的存儲位置來順序保存和訪問的。
關聯式容器也是用來存儲數據的,與序列式容器不同的是,關聯式容器邏輯結構通常是非線性結構,兩個位置有緊密的關聯關系,交換一下,他的存儲結構就被破壞了。順序容器中的元素是按關鍵字來保存和訪問的。關聯式容器有map/set系列和unordered map/unordered set系列。本章節講解的map和set底層是紅黑樹,紅黑樹是一顆平衡二叉搜索樹。set是key搜索場景的結構,map是key/value搜索場景的結構。

二、set系列

(1)set類的介紹

set的聲明如下圖,T就是set底層關鍵字的類型set默認要求T支持小于比較,如果不支持或者想按自己的需求走可以自行實現仿函數傳給第二個模版參數set底層存儲數據的內存是從空間配置器申請的,如果需要可以自己實現內存池,傳給第三個參數。
一般情況下,我們都不需要傳后兩個模版參數。set底層是用紅黑樹實現,增刪查效率是O(logN),迭代器遍歷是走的搜索樹的中序,所以是有序的。因為STL庫實現的接口相似度高,我們就不一一展示,挑選重要的來理解學習。

(2)set的構造和迭代器

迭代器是一個雙向迭代器。

set支持正向和反向迭代遍歷,遍歷默認按升序順序,因為底層是二叉搜索樹,迭代器遍歷走的中序;支持迭代器就意味著支持范圍for,set的iterator和const iterator都不支持迭代器修改數據,修改關鍵字數據,破壞了底層搜索樹的結構。

(3)set的接口

??1.insert

set的insert不支持插入相同的值。當然不管是不是const迭代器都不支持修改。

說明默認的insert作用就是去重和升序。如果我們想要變成降序的話,我們就需要增加仿函數這個參數。

對于列表值的插入,類似下圖。

接著我們也觀看一下構造中的列表初始化。下圖是先構造了個臨時對象,然后再拷貝構造出strset。

2.find和erase

find返回值是迭代器,成功返回要找的迭代器,返回失敗返回end的迭代器。

而erase刪除提供傳迭代器,傳數據,還可以傳迭代器區間。

這時候會有疑問,為什么第二個返回值不是bool而是size_type呢?這是為了兼容multiset,這里是刪除成功返回1刪除失敗返回0,在multiset中,刪除幾個返回多少。

我們通過一些例子去熟悉掌握這些接口。例如我們想把set中的最小值刪除,這里因為默認是升序,我們刪除begin迭代器即可。

例如我們如果要實現輸入一個值然后刪除。例如直接查找在利用迭代器刪除x。

這里erase后迭代器肯定失效。第一種是野指針,第二種是在替換法后當前位置的迭代器意義改變,也稱為迭代器失效

3.lower_bound和upper_bound

lower_bound返回大于等于val位置的迭代器,upper_bound則是返回大于val位置的迭代器

????????

這個有什么作用呢?假如我們需要刪除一段區間的值,而刪除一段區間需要左閉右開,這個時候我們就可以用上面兩個接口來獲得區間。

int main()
{set<int> myset;for (int i = 1; i < 10; i++)myset.insert(i * 10); for (auto e : myset){cout << e << " ";}cout << endl;auto itlow = myset.lower_bound(30);auto itup = myset.upper_bound(60);myset.erase(itlow, itup);for (auto e : myset){cout << e << " ";}cout << endl;return 0;
}

這樣我們就能夠刪除30到60之間的值。

(4)set和multiset的差異

multiset和set的使用基本完全類似,:要區別點在于multiset支持值冗余,insert/find/count/erase都圍繞著支持值冗余有所差異,具體參看下面的樣例代碼理解。相比set不同的是,multiset是排序,但是不去重

而find相比set也不同,不同的是,x可能會存在多個,find查找中序的第一個

count則會返回multiset中x的個數。

erase則會刪除所有的x。

三、map系列

(1)map類的介紹

map的聲明如下,Key就是map底層關鍵字的類型,T是map底層value的類型,set默認要求Key支持小于比較,如果不支持或者需要的話可以自行實現仿函數傳給第二個模版參數,map底層存儲數據的內存是從空間配置器申請的。一般情況下,我們都不需要傳后兩個模版參數。map底層是用紅黑樹實現,增刪查改效率是O(logN),迭代器遍歷是走的中序,所以是按key有序順序遍歷的 。

(2)pair類型介紹

我們先來了解一下map的插入,在了解插入之前我們需要去了解pair,因為插入的參數涉及到這個類型。

底層大概就是這樣,對比我們能夠知曉,first就是Key而second就是value。

typedef pair<const Key, T> value_type;
template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair() : first(T1()), second(T2()){}pair(const T1& a, const T2& b) : first(a), second(b){}template<class U, class V>pair(const pair<U, V>& pr) : first(pr.first), second(pr.second){}
};

所以我們在map中使用insert需要使用到pair。

(3)map的接口

1.insert

我們先前提到的pair就是我們在insert的時候所要使用到的,對于insert我們有多種形式insert。

第一種就是我們定義一個有名的pair對象,然后插入pair對象。

第二種我們可以插入一個匿名的pair對象。

第三種我們可以借用函數模板make_pair來插入,make_pair它會自己推導出后面的類型,返回一個pair對象。

C++11后提支持多參數隱式類型轉換后,我們就有了第四種方法insert。

在遍歷map的時候,與其他容器也有所不同,map沒有重載流插入和流提取,我們了解了pair的結構后我們需要去解引用后再調用first或者second。

在之前的學習中,我們能夠知曉迭代器不止重載了operator*還重載了operator->。剛好我們存儲的對象是結構,這樣我們就可以采用箭頭。

所以在map中我們常用箭頭來取對應的數據。我們要注意map中可以修改value,但不可以修改key

2.erase

erase還是只跟key有關,即使你map中沒有key也不會報錯。

3.operator[]

我們先來實現一個統計水果出現的次數。思路就是利用find和iterator修改功能,統計水果出現的次數。

但是實際上在map中不使用這種方式來實現,直接通過一行代碼就可以搞定。

這是怎么做到的呢?那我們需要來學習了解一下operator[]。這個接口提供了插入,查找和修改的功能。我們再回去觀看一下insert。

我們能夠發現這里其實有兩個pair。

我們重點要理解insert的返回值中的迭代器是什么意思呢?

所以返回的迭代器要么是新插入節點的迭代器,要么是插入失敗map里面和插入key相等的迭代器。bool則是根據插入成功失敗返回的。總結來說,insert如果插入成功返回的是pair<新插入值所在的迭代器,true>,插入失敗則是pair<已經存在的跟key相同值的迭代器,false>,所以insert不僅有插入的功能,還有查找的功能。insert插入失敗時充當了查找的功能,因為這一點,insert可以用來實現operator[]。

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

我們把operator[]內部實現大概的代碼拿出來研究一下。能夠得出:1、如果k不在map中,insert會插入k和mapped_type默認值,同時[]返回結點中存儲mapped_type值的引用,那么我們可以通過引用修改返映射值。所以[]具備了插入+修改功能。2、如果k在map中,insert會插入失敗,但是insert返回pair對象的first是指向key結點的迭代器,返回值同時[]返回結點中存儲mapped_type值的引用,所以[]具備了查找+修改的功能。

(4)multimap和map的差別

multimap和map的使用基本完全類似,主要區別點在于multimap支持關鍵值key冗余,那么insert/find/count/erase都圍繞著支持關鍵值key冗余有所差異,這里跟set和multiset完全一樣,比如find時,有多個key,返回中序第一個。其次就是multimap不支持[],因為支持key冗余,[]就只能支持插入了,不能支持修改。

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

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

相關文章

頭一次見問這么多kafka的問題

分享一篇粉絲朋友整理的面經&#xff0c;第一次遇見問那么多kafka的問題&#xff0c;看看他是怎么回答的。 先來看看 職位描述&#xff1a; 崗位職責&#xff1a; 負責基于 Go 的后端服務的設計、開發和維護&#xff1b;參與系統架構設計&#xff0c;確保系統的高可用性、高性能…

自底向上了解CPU的運算

文章目錄 引言 CPU如何實現邏輯運算 NMOS和PMOS 基于MOS管組合下的邏輯門運算 邏輯運算下運算的實現 ALU的誕生 CPU的誕生 關于二進制運算的研究 十進制轉二進制基礎換算 為什么負數要使用補碼進行表示 為什么反碼就能解決正負數相加問題,我們還需要用補碼來表示負數呢? 小數…

apache poi與Office Open XML關系

以下內容來自AI https://ecma-international.org/publications-and-standards/standards/ecma-376/ 官方規范 https://poi.apache.org/components/oxml4j/index.html java中針對Office Open XML的實現 Apache poi中各個組件 https://poi.apache.org/components/index.html …

S32K328上芯片內部RTC的使用和喚醒配置

1&#xff1a;RTC介紹 1.1 RTC基礎功能介紹 參考《S32K3xx Reference Manual》&#xff0c;S32K328芯片內部自帶RTC功能&#xff0c;并且支持從低功耗狀態下喚醒設備&#xff1b;1.2 RTC電源介紹 由以下三張圖可知 1&#xff1a;RTC由V11供電&#xff0c;V11依賴外部V15供電&am…

【Python】數據可視化之分類圖

目錄 條形圖 箱形圖 散點圖 分簇散點圖 小提琴 分簇小提琴 條形圖 條形圖是一種直觀的圖表形式&#xff0c;它通過不同長度的矩形條&#xff08;即“條形”&#xff09;來展示數值變量的中心趨勢估計值&#xff0c;其中每個矩形的高度直接對應于該組數據的某個中心量度&…

RabbitMQ模型詳解與常見問題

項目demo地址&#xff1a;https://github.com/tian-qingzhao/rabbitmq-demo 一、RabbitMQ組件概念 1.1 Server&#xff1a;接收客戶端的連接&#xff0c;實現AMQP實體服務。 1.2 Connection&#xff1a;連接 應用程序與Server的網絡連接&#xff0c;TCP連接。 1.3 Channel&…

網絡:相比于HTTP,HTTPS協議到底安全在哪?

網絡&#xff1a;相比于HTTP&#xff0c;HTTPS協議到底安全在哪&#xff1f; 我們知道HTTPS也是一種應用層協議&#xff0c;它在HTTP的基礎上有一層加密&#xff0c;因為HTTP的數據傳輸都是以明文方式傳輸的&#xff0c;所以加密主要是為了防止數據在傳輸的時候被篡改 今天我…

AI 基礎設施新范式,百度百舸 5.0 技術深度解析

本文整理自 2025 年 8 月 29 日百度云智大會 —— AI 算力平臺專題論壇&#xff0c;百度智能云 AI 計算首席科學家王雁鵬的同名主題演講。大家下午好&#xff01;昨天在主論壇&#xff0c;我們正式發布了百度百舸 AI 計算平臺 5.0&#xff0c;并展示了多項亮眼的性能數據。今天…

IO進程線程;多線程;線程互斥同步;互斥鎖;無名信號量;條件變量;0905

思維導圖多線程打印ABC運用無名面量 實現進程同步#include<myhead.h> //定義 無名信號量 sem_t sem1; sem_t sem2; sem_t sem3; //線程1 void* task1(void *arg) {while(1){sem_wait(&sem1);printf("A");fflush(stdout);sleep(1);sem_post(&sem2);} } …

固高 GTS-800 運動控制卡完全使用指南:從硬件部署到高階應用

固高 GTS-800 系列運動控制卡作為中端工業控制領域的標桿產品,以其 8-16 軸同步控制能力、豐富的插補功能和穩定的性能,廣泛應用于激光加工、PCB 制造、精密裝配等自動化設備中。本文將系統講解 GTS-800 的硬件架構、開發環境搭建、核心功能實現及工程實踐技巧,幫助工程師快…

STM32F103_Bootloader程序開發15 - 從Keil到vscode + EIDE + GCC的遷移實踐

導言 STM32 - Embedded IDE - GCC - 如何在工程中生成.bin格式固件 STM32 - Embedded IDE - GCC - 使用 GCC 鏈接腳本限制 Flash 區域 STM32 - Embedded IDE - GCC - 如何在工程中定義一段 NoInit RAM 內存 STM32 - Embedded IDE - GCC - 如何將編譯得到的.bin固件添加CRC32校驗…

HTTP協議——理解相關概念、模擬實現瀏覽器訪問自定義服務器

文章目錄HTTP協議理解相關概念HTTP相關背景知識認識URLHTTP協議在網絡通信的宏觀認識urlencode & urldecodeHTTP請求和應答的格式模擬實現瀏覽器訪問自定義服務器關于http requesthttp request的請求行——URI使用瀏覽器完成靜態資源的訪問常用的報頭屬性http response狀態…

【服務器】英偉達M40顯卡風冷方案心得

在之前的博文中&#xff0c;博主說到最近準備自己組裝一臺服務器&#xff0c;主要用于有限元仿真&#xff0c;其次兼顧一部分AI機器學習的工作&#xff0c;于是博主就入手了一張英偉達Tesla M40的12G顯卡GPU。本來博主也糾結過是買M40還是M60&#xff0c;后來在網上看到說M60看…

Java中的鎖升級機制

目錄 核心思想 Java對象頭&#xff08;Object Header&#xff09;與Mark Word 鎖升級的詳細步驟 1. 無鎖&#xff08;No Lock&#xff09; 2. 偏向鎖&#xff08;Biased Locking&#xff09; 3. 輕量級鎖&#xff08;Lightweight Lock&#xff09; 4. 重量級鎖&#xff…

Scikit-learn Python機器學習 - 特征預處理 - 標準化 (Standardization):StandardScaler

鋒哥原創的Scikit-learn Python機器學習視頻教程&#xff1a; 2026版 Scikit-learn Python機器學習 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 課程介紹 本課程主要講解基于Scikit-learn的Python機器學習知識&#xff0c;包括機器學習概述&#xff0c;特征工程(數據…

windows下wsl2 ubuntu開發配置

配置環境變量# 設置方式 命令/文件 生效范圍 適用場景 # 臨時 export FORCE_UNSAFE_CONFIGURE1 當前終端 臨時編譯軟件 # 用戶級永久 ~/.bashrc或~/.profile 當前用戶 長期使用&#xff08;單用戶&#xff09; # 系統級永久 /etc/environment或/…

網絡編程 05:UDP 連接,UDP 與 TCP 的區別,實現 UDP 消息發送和接收,通過 URL 下載資源

一、概述 記錄時間 [2025-09-02] 前置文章&#xff1a; 網絡編程 01&#xff1a;計算機網絡概述&#xff0c;網絡的作用&#xff0c;網絡通信的要素&#xff0c;以及網絡通信協議與分層模型 網絡編程 02&#xff1a;IP 地址&#xff0c;IP 地址的作用、分類&#xff0c;通過 …

告別線纜束縛!AirDroid Cast 多端投屏,讓分享更自由

AirDroid Cast 是一款功能強大的跨平臺投屏應用&#xff0c;能夠輕松實現手機、電腦之間以及手機之間的屏幕共享與控制。無論是工作演示、在線教學還是游戲直播&#xff0c;AirDroid Cast 都能提供流暢穩定的投屏體驗。 1. 下載與安裝 您可以通過以下鏈接下載 AirDroid Cast&…

從零開始學大模型之大模型訓練流程實踐

大模型訓練流程實踐 本文較長&#xff0c;建議點贊收藏&#xff0c;以免遺失。更多AI大模型開發 學習視頻/籽料/面試題 都在這>>Github<< >>Gitee<< 6.1 模型預訓練 在上一章&#xff0c;我們逐步拆解了 LLM 的模型結構及訓練過程&#xff0c;從零手…

一文從零部署vLLM+qwen0.5b(mac本地版,不可以實操GPU單元)

第一步&#xff1a;下載anaconda for mac https://zhuanlan.zhihu.com/p/350828057 知乎保姆級教程 https://www.anaconda.com/docs/getting-started/anaconda/install#macos-linux-installation 下載地址 第二步&#xff1a;部署vllm的虛擬環境 https://www.53ai.com/news/Op…