紅黑樹下探玄機:C++ setmultiset 的幕后之旅

目錄

一、關聯式容器

二、鍵值對

三、set

四、set的構造

五、set的iterator

六、set的Operations

七、multiset


一、關聯式容器

序列式容器 :?

  1. ?在初階階段,我們已經接觸過STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等
  2. 底層為線性序列的數據結構,里面存儲的是元素本身

關式容器聯 :?

  1. 也是用來存儲數據的,與序列式容器不同的是,其里面存儲的是<key, value>結構的鍵值對,在數據檢索時比序列式容器效率更高

二、鍵值對

鍵值對 :?用來表示具有一一對應關系的一種結構,該結構中一般只包含兩個成員變量key和value,key代表鍵值,value表示與key對應的信息

使用場景 :
現在要建立一個英漢互譯的字典,那該字典中必然有英文單詞與其對應的中文含義,而且,英文單詞與其中文含義是一一對應的關系,即通過該應該單詞,在詞典中就可以找到與其對應的中文含義

pair的結構

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)
{}
};

三、set

  • T: set中存放元素的類型,實際在底層存儲<value, value>的鍵值對
  • Compare:set中元素默認按照小于來比較
  • Alloc:set中元素空間的管理方式,使用STL提供的空間配置器管理

在使用set中,set相當于只存一個值,在set中,元素的value也標識它(value就是key,類型為T),并且每個value必須是唯一的,且set是按照一定次序存儲元素的容器

在內部,set中的元素總是按照其內部比較對象(類型比較)所指示的特定嚴格弱排序準則進行排序,set中的元素按一定次序排序,且元素唯一,元素不能在set中被修改 (元素總是const) ,只能被插入或刪除 ,set在底層是用二叉搜索樹(紅黑樹)實現的

注意記憶的點:

  • set中只放value,但在底層實際存放的是由<value, value>構成的鍵值對
  • set中插入元素時,只需要插入value即可,不需要構造鍵值對pair
  • ?set中的元素不可以重復(因此可以使用set進行去重)
  • 使用set的迭代器遍歷set中的元素,可以得到有序序列
  • set中的元素默認按照小于來比較
  • set中查找某個元素,時間復雜度為:log2(N)

四、set的構造

  1. empty : set的無參的構造?
  2. range :使用一段迭代器區間構造
  3. copy :拷貝構造?

operator=

#include <iostream>
#include <set>using namespace std;int main()
{set<int> s1;int arr[] = { 9,8,7,6,5,4,3 };set<int> s2(arr, arr + sizeof(arr) / sizeof(arr[0]));set<int> s3(s2);s1 = s2;return 0;
}


五、set的iterator

  • 返回第一個元素的iterator

  • 返回最后一個元素的iterator
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2(arr, arr + sizeof(arr) / sizeof(arr[0]));set<int>::iterator it = s2.begin();set<int>::iterator it1 = s2.end();while (it != it1){cout << *it << " ";it++;}return 0;
}


  • 判斷set是否為空

  • 返回set的元素個數

  • single element : 插入一個key(val)返回一個鍵值對pair,在pair中第一個數據first是插入位置的迭代器,第二個位置是->是否插入成功,set中的key值不能重復且只能有一個,如果key值已經有了,那么返回的是原key位置的迭代器以及false,如果key值沒有,那么返回的是新插入key位置的迭代器以及true,由于return不能返回兩個值,所以如果想返回多個值,必須放在一個結構中進行返回,這里是放在了鍵值對pair中進行返回
  • with hint :?在一個迭代器位置插入一個key(val),傳入的這個iterator 位置對于編譯器來說只是一個建議位置,實際插入數據還是根據其原有的二叉搜索樹的邏輯 (有序) 進行插入
  • range : 是插入一段迭代器區間
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));set<int>::iterator it=s2.insert(s2.begin(), 2);cout << *it << endl;pair<set<int>::iterator, bool> pa = s2.insert(9);cout << *(pa.first) << " "<<pa.second << endl;return 0;
}


  • void erase : 刪除某個 iterator?
  • size_ t erase :?刪除某個key值,返回值是刪除的這個key值的個數 , 返回的個數這是為了后面的 multiset 做準備,因為multiset可以允許有多個相同的key值,而set和mulitset的關聯性很大,所以為了接口的統一性將這里的刪除值為key的erase的操作的返回值設置為了返回刪除key值的個數,在set中當有這個key值的 時候刪除對應的節點成功返回1,當沒有這個key值的時候刪除對應節點失敗返回 0
  • void erase :?刪除一段迭代器區間
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));s2.erase(s2.begin());size_t ret = s2.erase(8);cout << ret << endl;s2.erase(s2.begin(), s2.end());return 0;
}


  • swap是交換兩個set對象的數據
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));set<int> s3;s3.swap(s2);return 0;
}


  • 清空set的所有元素
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));s2.clear();return 0;
}


六、set的Operations

  • find是查找一個元素的iterator,如果沒有查找到那么返回end()iterator
  • set的底層是紅黑樹,在二叉搜索數的基礎上進行了平衡,所以成員函數find的查找效率高為O(logN),,庫里也有find,由于庫里的是給出區間遍歷查找,時間復雜度為O(N) ,所以單獨提供了find
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));cout << *(s2.find(9)) << endl;return 0;
}


  • count是返回key值對應的個數 ,同樣是為了和multiset保持接口的一致性,multiset允許多個key值存在,所以當myltiset調用count的時候可能key值對應的個數會有多個,為了set和multiset接口的統一性,我們給set也提供一個count接口,count接口在set中可以用于判空
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));cout << s2.count(7) << endl;return 0;
}


  • lower_bound是下界(>=)的意思,即尋找比給定key值等于大于的值的位置的迭代器,有等于優先是等于,其次是大于,如果找不到那么返回end()

  • upper_bound(>)是上界的意思,即尋找比給定key值大的值的位置的迭代器,如果找不到那么返回end()

lower_bound和upper_bound通常是搭配使用,用于尋找指定區間的迭代器(前閉區間 ,后開區間),通常要使用erase或insert插入一段區間,對區間進行操作,那么就會用到這兩個函數

erase:

#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3 };set<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));set<int>::iterator it1 = s2.lower_bound(5);// >=5set<int>::iterator it2 = s2.upper_bound(6);// >6// erase: [5 ,6 ) ,刪除掉 5 和6  s2.erase(it1, it2);for (auto e : s2){cout << e << endl;}return 0;
}


  • equal_range的意思是相等的范圍,即去尋找和key值相等序列的開頭和結尾位置的迭代器,同理 ,這里同樣是為了和multiset保持接口的一致性,即multiset中可以有多個相同的key值,即使用equal_range去找key值會找到的是一段序列
  • 返回的pair中第一個iterator 是?和key值相等序列的開頭位置的iterator , 第二個是結尾位置的迭代器?
  • 如果給equal_range的key值,在set中沒有,那么會返回比key值大的位置的迭代器作為開頭位置的迭代器和結尾位置的迭代器進行返回,舉例set數據序列為1,5,7,那么傳入查找3作為key值進行查找,3沒有,那么就會找比key值3大的值的迭代器即5位置的迭代器作為開頭和結尾位置的迭代器,那么就會返回[5,5),那么由于成員函數對序列區間進行操作是前閉區間后開區間,那么[5,5)這個序列就相當于不存在的區間,如果比key值(key值不存在set的數據序列中)大的位置的值都沒有那么會返回end()作為開頭和結尾的位置的迭代器即[end(),end()),即如果給equal_range的key值不存在,那么equal_range會返回一個不存在的區間

七、multiset

  • multiset與set 的唯一不同是multiset中可以有多個相等的key值
  • multiset的其它性質和set類似
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3,8,7,6,5,4,3,8 };multiset<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));for (auto e : s2){cout << e <<" ";}cout << endl;return 0;
}

multiset的count

#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3,8,7,6,5,4,3,8 };multiset<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));cout << s2.count(9);cout << endl;cout << s2.count(7) << endl;return 0;
}

multiset的erase

  • 與set不同的是,multiset刪除key值,如果key值有多個,那么會將多個相同的key值同時刪除
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3,8,7,6,5,4,3,8 };multiset<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));s2.erase(4);for (auto e : s2){cout << e << " ";}return 0;
}

multiset的find

  • 與set不同的是,multiset的find的key值可能會有對應的多個相等的key值,那么find會返回迭代器遍歷(中序遍歷)中的第一個key值位置的迭代器
#include <iostream>
#include <set>
using namespace std;
int main()
{int arr[] = { 9,8,7,6,5,4,3,8,7,6,5,4,3,8 };multiset<int> s2;s2.insert(arr, arr + sizeof(arr) / sizeof(arr[0]));set<int>:: iterator it = s2.find(7);//找到第一個7cout << *(it) << endl;it++;cout << *(it) << endl;//是按有序的排列,第一個7后面也是7  ,說明是第一個7return 0;
}

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

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

相關文章

Spring : 事務管理

1. 基本概念 事務&#xff08;Transaction&#xff09;是一組不可分割的操作單元&#xff0c;這些操作要么全部成功執行&#xff0c;要么全部失敗回滾&#xff0c;不存在部分成功的情況。 事務具有ACID特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事…

C# 一個投資跟蹤程序的設計與實現:面向對象與設計模式的深度解析

在現代金融應用開發中&#xff0c;如何高效、靈活地構建投資跟蹤系統&#xff0c;是每一個金融軟件工程師必須面對的挑戰。本文將圍繞一個投資跟蹤程序的設計與實現過程&#xff0c;深入剖析其背后的設計理念、架構模式以及具體實現細節。我們將通過面向對象編程、設計模式&…

存儲的未來之戰:RustFS如何用ZK框架重構分布式協調?

本篇文章目錄 一、導火索&#xff1a;當數據洪峰撞上分布式協調的天花板 二、技術密碼&#xff1a;ZK框架的三大重構 2.1 一致性哈希環的量子級進化 2.2 動態負載均衡的"神經反射" 2.3 跨云數據同步的"時空折疊" 三、未來戰爭&#xff1a;2026年存儲…

模擬實現STL中的list容器

list前言一、list的節點結構設計二、迭代器設計三、list類的實現3.1 類的成員變量和類型定義3.2 構造函數與析構函數3.3 元素訪問與迭代器接口3.4 插入與刪除操作3.5 其他常用操作四、總結每文推薦前言 在C STL中&#xff0c;list是一個非常常用的容器&#xff0c;它基于雙向循…

Debug-039-el-date-picker組件手動輸入時間日期的問題處理

圖1-外輸入框圖2-內輸入框圖3問題描述&#xff1a;這兩天在迭代功能的時候&#xff0c;基本上碰到的問題都是出自這個“時間日期選擇框”&#xff0c;昨天的bug38也是解決這個組件。如上圖1和2所示&#xff0c;可以把圖1中的輸入框叫外輸入框&#xff0c;圖2中的輸入框叫內輸入…

docker-runc not installed on system

問題 Docker build時Dockerfile有RUN命令執行報錯shim error: docker-runc not installed on system&#xff0c;如下&#xff1a;解決方法 修改/etc/docker/daemon.json&#xff0c;添加正面內容 {"runtimes": {"docker-runc": {"path": "…

【秋招筆試】2025.08.27華為秋招研發崗真題

?? 點擊直達筆試專欄 ??《大廠筆試突圍》 ?? 春秋招筆試突圍在線OJ ?? 筆試突圍在線刷題 bishipass.com 題目一:智能溫控系統監測 1??:使用滑動窗口技術維護有效溫度區間 2??:利用單調隊列高效維護窗口內的最大值和最小值 3??:動態調整窗口邊界,確保滿足溫…

Kafka 消費模型

文章目錄1. 一個消費者組中只有 1 個消費者2. 一個消費者組中有 2 個消費者3. 消費者數量 > 分區數量4. 多個消費者讀取同一個分區5. 消費者放入消費者組5.1 何時放入同一個消費者組5.2 何時放入不同的消費者組1. 一個消費者組中只有 1 個消費者 假設我們有一個 TopicT1&am…

【路由器】TP Link 路由器為何無法進入管理后臺

TL-WR710N是TP Link在很多年前發布的一個迷你型的便攜路由器&#xff0c;一插上還能用&#xff0c;直接reset打算重設密碼&#xff0c;結果根據它給的192.168.1.253根本打不開。# 解決方法ping一下192.168.1.253&#xff0c;無法連接。這個問題本質上是 你電腦/手機的 IP 和路由…

LightGBM(Light Gradient Boosting Machine,輕量級梯度提升機)梳理總結

LGB微軟團隊在 2017 年提出的梯度提升樹模型&#xff0c;核心定位是 “更高效的 XGBoost”—— 它在保持精度接近 XGBoost 的同時&#xff0c;通過“數據采樣優化”“特征壓縮”“樹生長策略改進”三大創新&#xff0c;將訓練速度提升 10-100 倍&#xff0c;內存消耗降低數倍&a…

畢業項目推薦:29-基于yolov8/yolov5/yolo11的光伏板檢測識別系統(Python+卷積神經網絡)

文章目錄 項目介紹大全&#xff08;可點擊查看&#xff0c;不定時更新中&#xff09;概要一、整體資源介紹技術要點功能展示&#xff1a;功能1 支持單張圖片識別功能2 支持遍歷文件夾識別功能3 支持識別視頻文件功能4 支持攝像頭識別功能5 支持結果文件導出&#xff08;xls格式…

【實時Linux實戰系列】實時數據可視化技術實現

在當今數據驅動的世界中&#xff0c;實時數據可視化已成為理解和利用實時信息的關鍵工具。無論是在金融交易監控、工業生產監控、智能交通管理還是物聯網設備監控中&#xff0c;能夠將復雜的數據以直觀的圖表形式展示出來&#xff0c;對于快速決策和問題解決至關重要。實時數據…

【LeetCode每日一題】21. 合并兩個有序鏈表 2. 兩數相加

每日一題21. 合并兩個有序鏈表題目總體思路算法步驟時間復雜度與空間復雜度代碼2. 兩數相加題目總體思路算法步驟時間復雜度與空間復雜度代碼知識感悟2025.8.3021. 合并兩個有序鏈表 題目 將兩個升序鏈表合并為一個新的 升序 鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所…

DVWA靶場通關筆記-文件包含(Impossible級別)

目錄 一、源碼分析 二、文件包含防范分析 1、明確指定允許包含的文件 2、拒絕所有未在白名單中的輸入 3、總結 &#xff08;1&#xff09;白名單 (Allow List) &#xff08;2&#xff09;硬編碼/映射 (Hardcoding/Mapping) &#xff08;3&#xff09;輸入過濾 (Input F…

構建堅不可摧的數據堡壘:深入解析 Oracle 高可用與容災技術體系

在當今數字化時代&#xff0c;數據是企業的核心資產&#xff0c;而承載這些數據的數據庫系統的連續性與穩定性直接關系到企業的生死存亡。一次計劃外的停機或災難性的數據丟失&#xff0c;帶來的不僅是經濟上的巨大損失&#xff0c;更是對品牌信譽和客戶信任的致命打擊。因此&a…

【3D算法技術入門】如何基于建筑圖片重建三維數字資產?

要基于建筑圖片重建三維數字資產是一個復雜的計算機視覺任務&#xff0c;涉及圖像采集、特征提取、相機姿態估計、稠密重建和三維模型優化等多個步驟。下面我將提供一個基于Python的解決方案框架&#xff0c;使用開源庫實現從圖片到三維模型的基本流程。 首先需要安裝必要的庫&…

?CVPR2025 自動駕駛半監督 LiDAR 分割新范式:HiLoTs 框架深度解析

&#x1f4c4;論文題目&#xff1a;HiLoTs: High-Low Temporal Sensitive Representation Learning for Semi-Supervised LiDAR Segmentation in Autonomous Driving ??作者及機構&#xff1a; R.D. Lin、Pengcheng Weng、Yinqiao Wang、Fei Wang&#xff08;西安交通大學軟件…

【 MYSQL | 基礎篇 函數與約束 】

摘要&#xff1a;本文介紹數據庫中的函數與約束&#xff0c;函數含字符串、數值、日期、流程四類&#xff0c;可實現字符串處理、數值計算等需求。約束分六類&#xff0c;重點講外鍵約束的語法、刪除更新行為&#xff0c;保證數據正確完整。思維導圖1. 函數函數是指一段可以直接…

Oracle 數據庫性能調優:從瓶頸診斷到精準優化之道

引言&#xff1a;性能優化的本質在當今數據驅動的時代&#xff0c;數據庫性能直接關系到企業的運營效率和用戶體驗。Oracle 作為全球領先的關系型數據庫管理系統&#xff0c;承載著眾多企業的核心業務。然而&#xff0c;隨著數據量的增長和業務復雜度的提升&#xff0c;數據庫性…

楊校老師競賽課堂之C++語言GESP一級筆記

考試大綱 GESP一級考試大綱 計算機基礎與編程環境 計算機歷史 變量的定義與使用 基本數據類型&#xff08;整型、浮點型、字符型、布爾型&#xff09; 輸入與輸出&#xff08;cin與cout、scanf與printf&#xff09; 基本運算&#xff08;算術運算、關系運算、邏輯運算&am…