【C++】來學習使用set和map吧

在這里插入圖片描述
各位大佬好,我是落羽!一個堅持不斷學習進步的大學生。
如果您覺得我的文章有所幫助,歡迎多多互三分享交流,一起學習進步!

也歡迎關注我的blog主頁: 落羽的落羽

文章目錄

  • 一、set和map是什么
  • 二、set系列
    • 1. set
    • 2. multiset
  • 三、map系列
    • 1. map
    • 2. multimap

一、set和map是什么

我們之前已經學習過了STL庫中的部分容器,如string、vector、list、deque,這些容器統稱之為序列式容器,因為它們的邏輯結構都是線性的,存儲元素之間一般沒有緊密的聯系關系,即使交換元素位置,數據結構仍是線性的。這些序列式容器的元素是按照他們在容器中存儲的位置來順序保存和訪問的。

關聯式容器的邏輯結構則是非線性的結構,元素位置之間有緊密的關聯關系,交換位置則存儲結構會破壞。關聯式容器有map/set系列和unordered_map/unorderer_set系列。

今天我們學習的set和map,底層是紅黑樹,紅黑樹是一棵平衡二叉搜索樹。set是key搜索場景的結構,而map是key/value搜索場景的結構。

二、set系列

使用set系列的set、multiset,都需要#include <set>

1. set

set是不允許key值重復出現的平衡二叉搜索樹。

在這里插入圖片描述

  • set的模板參數T,就是key的類型。
  • set默認要求key值是小于比較,也就是這棵樹中左子樹key < 結點key < 右子樹key,因為第二個模板參數默認傳的是less<T>。我們也可以自己傳greater<T>使之變成大于比較,即這棵樹中左子樹key > 結點key > 右子樹key。
  • 由于set底層是紅黑樹,增刪查效率是O(logN),效率很高,中序遍歷默認是升序的。

set的幾種構造方式:
在這里插入圖片描述

set也有迭代器,也有begin和end一系列接口。在這里插入圖片描述
set的begin()和end()是它的中序遍歷序列的開頭和結尾,begin是中序第一個結點,end是中序的最后一個結點的下一個位置。后面的容器也是一樣,begin和end都是中序遍歷的位置。不難想象,begin()返回的是最小key值結點的迭代器
set支持正向和反向迭代器,也支持范圍for,迭代器++和范圍for都是按照樹的中序順序進行遍歷。但是set的iteritor和const_iteritor都不支持迭代器修改key,會破壞底層搜索樹的結構。

在這里插入圖片描述

set類中當然還有增刪查等相關功能:

  • find:查找key為傳參val的位置,若存在則返回這個位置的迭代器,若不存在則返回end()在這里插入圖片描述

  • count:記錄set中key為傳參的結點個數在這里插入圖片描述
    這個函數的返回值是size_t類型,是key值為val的個數,但是由于set中不允許有重復key值,所以set類對象這個函數的返回值只能是0或1,也就可以依據是0或1判斷某個key是否存在。換句話說,count也可以有查找判斷key是否存在的功能。

  • insert:插入新的key在這里插入圖片描述 insert可以插入單個數據、一段迭代器區間、一段{ }列表。但由于set不允許有重復key值,所以插入內容中出現了重復key值則不會插入。這個過程實際是先進行了一次查找操作,在原set中找不到想新插入的key,才能進行插入

  • erase:刪除結點在這里插入圖片描述
    erase可以傳一個迭代器刪除這個迭代器的結點,可以傳一段迭代器區間整體刪除。也可以傳一個key值刪除這個key值的結點,找不到這個key結點則不刪除,這種版本的erase返回值是size_t,和count道理一樣,返回值代表刪除的結點個數,1代表刪除了一個結點,0代表沒有刪除結點,也可以用于判斷刪除是否成功。

演示:
在這里插入圖片描述

除此之外,set還有兩個接口lower_bound、upper_bound:
在這里插入圖片描述

在這里插入圖片描述

它們通常一起使用,lower_bound返回set中的第一個key值>=val值的結點的迭代器,upper_bound返回set中的第一個key值>val值的結點的迭代器它們的作用是找一段值的區間
比如一個set中結點為{10, 20, 30, 40, 50, 60, 70, 80, 90}auto it1 = lower_bound(30);
則it1是結點30的迭代器,auto it2 = upper_bound(70);,則it2是結點70的迭代器。也就是說,it1和it2兩個迭代器包含了30、40、50、60、70這段結點區間。
這兩個函數的傳參可以不是set中已存在的key值,比如上面的例子,傳auto it1 = lower_bound(35);則it1是結點40的迭代器,auto it2 = upper_bound(75);,則it2是結點80的迭代器。
若它們找不到比val大的key結點,則返回end()。

演示:
在這里插入圖片描述

2. multiset

multiset也是set系列的一種,相比于set,它支持key值的冗余,也就是可以存在重復的key值。相同的key可能在根結點key的左邊或右邊。它的使用與set大體類似,但find、insert、erase、count等與set的有所差異:

  • find:multiset的key中可能有多個為val的結點。multiset的find是按照中序序列查找第一個key為val的結點,返回它的迭代器。
  • insert:multiset支持存在重復的key,因此插入已存在key值的新結點也能成功。
  • erase:multiset的這種erase版本size_type erase (const value_type& val);會刪除所有key值為val的結點,返回值是刪除的結點的個數。因為multiset中可能有重復key值,所以返回值可能是任何非負整數。
  • count:和set一樣,也是記錄返回key值為傳參val的結點個數。因為multiset中可能有重復key值,所以返回值可能是任何非負整數。

只要理解了multiset和set的差異只在于muliset支持key重復存在,它們的接口的差異都很好理解了。

演示:在這里插入圖片描述

multiset也有lower_bound和upper_bound操作,和set道理一樣。

multiset中還有一個equal_range,是查找key值為傳參val的結點的區間。因為multiset中若有重復的key結點,則它們在中序序列中一定是連續的。equal_range就返回這一段迭代器區間。注意到它的返回類型是pair<iteritor, iteritor>,這就是兩個迭代器的組合代表一段區間,關于pair具體下面再介紹。在這里插入圖片描述

三、map系列

使用map系列的map、multimap,都需要#include <map>

1. map

set系列底層是key結構的紅黑樹,而map系列底層是key/value結構的紅黑樹。
map不允許key值重復出現的平衡二叉搜索樹。

在這里插入圖片描述

其中,Key是key的類型,T是value的類型。Compar默認傳less要求支持小于比較。map的增刪查改效率是O(N),迭代器也是走的中序遍歷,按照key的有序順序進行遍歷。
而在map的結點中,它的key和value其實是被封裝成一個叫pair的結構體來存儲的:

在這里插入圖片描述

pair的結構其實很簡單,就是兩個類型的兩個成員封裝在一起,T1 firstT2 second。在map的結點中的pair,T1為key的類型,T2為value的類型,first就是key,second就是value。map的結點中,使用pair<Key, T>存儲鍵值對數據。當然,pair類型中還有一些構造函數、拷貝構造函數,不多贅述。

map的構造、迭代器、其他操作大體和set都是相似的,區別只在于map可以修改value值,不能修改key值。查和刪的操作只關注key,所以map的查和刪和set一樣。增的操作不僅要增key,還要增value:

在這里插入圖片描述
第一個版本的insert返回類型是pair<iterator, bool>如果key已在map中,則插入失敗,返回的pair的first是已存在key所在節點的迭代器,second是false;如果key不在map中,插入成功,返回的pair的first是新插入key的結點迭代器,second是true。也就是說,無論key插入失敗成功,insert的返回值的first都是key結點的迭代器,意味著insert也能充當查找的功能,下面[ ]的重載就是利用了這一點。
insert要求的參數是一個pair,這里其實就很靈活了。可以構造對象再傳參、匿名對象傳參、隱式類型轉換傳參:
在這里插入圖片描述

相比set,map還可以修改value的功能。一種方法是通過迭代器,map的迭代器相當于指向pair的指針,利用迭代器->second = x;來完成修改。
另一種方法,map重載了[]操作符,但是用法很特殊:map的[ ]中不是傳尋常的下標,而是傳key值,若這個key值在map中已存在,則返回它對應的value的引用;若這個key值不存在,則將這個key新插入進去,它的value則使用它的缺省值或調它的類型的默認構造,也返回value的引用。

value若是自定義類型,就有它的默認構造;內置類型也有默認構造,如int默認構造為0,指針默認構造為nullptr。

不難看出,[ ]有查找+插入的功能,同時因為返回value的引用,也具備了修改的功能。map的[ ]重載是一個非常重要的多功能接口,它的內部實現是這樣的,利用剛才說的insert的特點:

T& operator[](const Key& key)
{pair<iterator, bool> ret = insert({key, T()});//it指向了key值的結點,不論這個key是已存在的還是新插入的iterator it = ret.first;//it相當于指向了pair,it的second就是value了return it->second;
}

map的[ ]在一些特定場景下使用是很爽的,比如這樣一個例子:統計字母出現個數。
不使用[ ]可能要這么做:

vector<char> v = { 'a','b','c','b','a','c','a','a','b' };//構建一個map<char,int>,char代表字母,int代表它的出現次數
map<char, int> countMap;for (auto e : v)
{//查找字母在不在map中auto ret = countMap.find(e);//不在,說明這個字母是第一次出現,插入{字母,1}if (ret == countMap.end()){countMap.insert({ e,1 });}//這個字母存在,則它的出現次數+1else {ret->second++;}
}for (auto e : countMap)
{cout << e.first << ":" << e.second << "次" << endl;
}
cout << endl;

在這里插入圖片描述

但使用[ ],就更簡潔了:

vector<char> v = { 'a','b','c','b','a','c','a','a','b' };//構建一個map<char,int>,char代表字母,int代表它的出現次數
map<char, int> countMap;for (auto e : v)
{//字母不在,說明這個字母第一次出現,則插入,int默認構造成0,++一下就成1了//字母在,也返回value的引用,也會++一次countMap[e]++;
}for (auto e : countMap)
{cout << e.first << ":" << e.second << "次" << endl;
}
cout << endl;

在這里插入圖片描述
沒有問題!

2. multimap

multimap就是支持key重復出現的map,同一key值的不同結點的value也可以不一樣。multimap的增刪查改相對于map也有一些不同,但是大概規律和multiset相對于set一樣,比如find返回多個key值結點的中序遍歷第一個。除此之外就是multimap不支持map的[ ]

本篇完,感謝閱讀~

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

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

相關文章

h5st逆向分析

h5st最新5.1版本逆向分析 申明定位h5st生成的位置動態插樁,事半功倍日志分析,十分鐘還原算法邏輯申明 本文僅用來記錄學習過程以免日后忘了,如有侵權請聯系刪除。 定位h5st生成的位置 通過關鍵字“sign”搜索,可以定位到window.PSign.sign(f)這個位置,f參數的值為{ &qu…

湖北理元理律師事務所企業債務優化路徑:司法重整中的再生之道

一、企業債務危機的核心矛盾&#xff1a;生存與清償的博弈 通過分析湖北理元理律師事務所經辦的17件企業債務案件&#xff0c;發現共性難題&#xff1a; 債權人要求立即清償 → 企業需持續經營造血 → 司法程序存在時間差 解決方案&#xff1a;構建“三重防火墻”機制 經…

鏈家Android面試題及參考答案

目錄 請詳細解釋類加載的過程,包括每一步的具體實現。并說明Android中的dex分包技術及其在熱更新中的應用 比較JVM和DVM的區別。在JVM中一個程序崩潰是否可能導致系統崩潰?DVM中呢? 請解釋網絡IP協議、TCP、UDP、HTTP、HTTPS、Socket的概念,并說明它們之間的區別 請深入…

LeetCode-多語言實現冒泡排序以及算法優化改進

目錄 一、冒泡排序算法 二、應用場景/前提條件 &#x1f308; 優點 &#x1f4e2; 缺點 三、經典算法實現并優化改進 方法一&#xff1a;記錄最后一次交換位置&#xff0c;下一輪只遍歷到該位置 方法二&#xff1a;添加標志位跟蹤是否發生交換&#xff0c;無交換則提前終…

JAVA畢業設計227—基于SpringBoot+hadoop+spark+Vue的大數據房屋維修系統(源代碼+數據庫)

畢設所有選題&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于SpringBoothadoopsparkVue的大數據房屋維修系統(源代碼數據庫)227 一、系統介紹 本項目前后端分離&#xff0c;分為業主、維修人員、管理員三種角色 1、業主&#xff1a; 登…

MADlib —— 基于 SQL 的數據挖掘解決方案(9)—— 數據探索之概率統計

目錄 一、概率 1. 概率的定義 2. 概率質量函數與概率密度函數 3. 條件概率 4. 期望值 二、MADlib 的概率相關函數 1. 函數語法 2. 示例 &#xff08;1&#xff09;求標準正態分布下&#xff0c;1 的概率密度函數 &#xff08;2&#xff09;求標準正態分布下&#xff…

耳蝸里的春天

早春的鄭州飄著細雨&#xff0c;我牽著女兒小滿的手走進市殘疾人康復中心時&#xff0c;玻璃門內突然傳來一陣清脆的笑聲。穿天藍色毛衣的小女孩戴著粉色耳蝸&#xff0c;正踮腳拍打著墻上的卡通貼畫&#xff0c;銀色的連接線在她耳后晃動&#xff0c;像一只折翼卻仍在起舞的蝴…

OCR(光學字符識別)算法

OCR&#xff08;光學字符識別&#xff09;算法在景區護照閱讀器中的應用是核心技術之一&#xff0c;它通過圖像處理和機器學習快速提取護照信息&#xff0c;顯著提升自動化水平。以下是其具體應用場景、技術實現及優化方向&#xff1a; 一、OCR在護照閱讀器中的核心作用 關鍵信…

html打印合同模板

概述&#xff08;吐槽&#xff09;&#xff1a;記錄一個html打印合同模板的功能&#xff0c;技術棧有點雜&#xff0c;千禧年出產老系統的數據庫是sqlserver2008&#xff0c;原系統框架是c#&#xff0c;無法二開&#xff0c;因為原系統的合同生成功能出現bug&#xff0c;沒有供…

DeepCritic: SFT+RL兩階段訓練突破LLM自我監督!顯著提升大模型的自我批判能力!!

摘要&#xff1a;隨著大型語言模型&#xff08;LLMs&#xff09;的迅速發展&#xff0c;對其輸出進行準確反饋和可擴展監督成為一個迫切且關鍵的問題。利用LLMs作為批評模型以實現自動化監督是一個有前景的解決方案。在本研究中&#xff0c;我們專注于研究并提升LLMs在數學批評…

【深度學習】深度學習中的張量:從多維數組到智能計算單元

? 一、n維數組&#xff08;張量&#xff0c;Tensor&#xff09; 1. 定義 張量&#xff08;Tensor&#xff09;是一個通用的n維數組數據結構。 它的維度&#xff08;維數&#xff09;決定了它的形狀&#xff0c;例如&#xff1a; 維度名稱舉例說明0維標量&#xff08;scalar…

以太網MDI信號PCB EMC設計要點

1. PHY側和RJ45連接器側通用MDI布局建議 1. MDI差分對保持對稱走線&#xff0c;走線上的焊盤封裝應一致&#xff0c;焊盤放置位置也應對稱。可以減少EMI測試中的模式轉換。 ??2. MDI走線應保持阻抗匹配&#xff0c;從而減少信號線上的反射。 ??3. MDI走線下需有連續完整的接…

深入淺出WebGL:在瀏覽器中解鎖3D世界的魔法鑰匙

WebGL&#xff1a;在瀏覽器中解鎖3D世界的魔法鑰匙 引言&#xff1a;網頁的邊界正在消失 在數字化浪潮的推動下&#xff0c;網頁早已不再是靜態信息的展示窗口。如今&#xff0c;我們可以在瀏覽器中體驗逼真的3D游戲、交互式數據可視化、虛擬實驗室&#xff0c;甚至沉浸式的V…

pysnmp模塊中 GET、SET、WALK操作詳細分步解析

1. SNMP GET 操作詳解 1.1 核心代碼結構 from pysnmp.hlapi import *# 定義參數 community public # SNMPv2c 社區名 target_ip 192.168.1.1 # 目標設備 IP oid 1.3.6.1.2.1.1.1.0 # 要查詢的 OID# 發起 GET 請求 error_indication, error_status, error_index, …

接收rabbitmq消息

以下是一個使用純Java&#xff08;非Spring Boot&#xff09;接收RabbitMQ消息的完整實現&#xff0c;包含Maven依賴和持續監聽消息的循環&#xff1a; 1. 首先添加Maven依賴 (pom.xml) <dependencies><!-- RabbitMQ Java Client --><dependency><group…

SQL進階之旅 Day 23:事務隔離級別與性能優化

【SQL進階之旅 Day 23】事務隔離級別與性能優化 文章簡述 在數據庫系統中&#xff0c;事務是確保數據一致性和完整性的核心機制。隨著業務復雜度的提升&#xff0c;如何合理設置事務隔離級別以平衡并發性能與數據一致性成為開發人員必須掌握的關鍵技能。本文深入解析事務隔離級…

六.原型模式

一.原型模式的定義 原型模式是一種創建型設計模式&#xff0c;通過復制現有對象&#xff08;原型&#xff09;生成新對象&#xff0c;避免重復初始化成本。需了解以下關鍵概念&#xff1a; ?淺拷貝?&#xff1a;復制基本類型字段&#xff0c;引用類型字段共享內存地址&#…

【筆記】LoRA 理論與實現|大模型輕量級微調

論文鏈接&#xff1a;LoRA: Low-Rank Adaptation of Large Language Models 官方實現&#xff1a;microsoft/LoRA 非官方實現&#xff1a;huggingface/peft、huggingface/diffusers 這篇文章要介紹的是一種大模型/擴散模型的微調方法&#xff0c;叫做低秩適應&#xff08;也就是…

Cilium動手實驗室: 精通之旅---15.Isovalent Enterprise for Cilium: Network Policies

Cilium動手實驗室: 精通之旅---15.Isovalent Enterprise for Cilium: Network Policies 1. 環境信息2. 測試環境部署3. 默認規則3.1 測試默認規則3.2 小測驗 4. 網絡策略可視化4.1 通過可視化創建策略4.2 小測試 5. 測試策略5.1 應用策略5.2 流量觀測5.3 Hubble觀測5.4 小測試 …

opencv RGB圖像轉灰度圖

這段代碼的作用是將一個 3通道的 RGB 圖像&#xff08;CV_8UC3&#xff09;轉換為灰度圖像&#xff08;CV_8UC1&#xff09;&#xff0c;并使用 OpenCV 的 parallel_for_ 對圖像處理進行并行加速。 &#x1f50d; 一、函數功能總結 if (CV_8UC3 img.type()) {// 創建灰度圖 d…