【C++】: STL詳解 —— set和map類

目錄

關聯式容器

鍵值對

set

set的概念

set的構造函數

set的使用

map

map的概念

map的構造函數

map的使用

multiset

multimap


關聯式容器

C++標準庫提供了多種容器,用于高效管理和操作數據集合。這些容器可分為以下幾類:

  1. 順序容器(Sequence Containers)

  2. 關聯容器(Associative Containers)

  3. 容器適配器(Container Adapters)

  4. 其他類容器類型

?順序容器:核心是元素的線性存儲,支持隨機或順序訪問

容器分類容器類C++標準描述
順序容器vectorC++98動態數組,支持快速隨機訪問,尾部操作高效。
listC++98雙向鏈表,任意位置插入/刪除高效,不支持隨機訪問。
dequeC++98雙端隊列,頭尾插入/刪除高效,支持隨機訪問。
arrayC++11固定大小數組,安全性優于內置數組,編譯時確定大小。
forward_listC++11單向鏈表,節省內存,僅支持單向遍歷。

?關聯容器:基于鍵(Key)組織數據,有序容器(紅黑樹)與無序容器(哈希表)區分明顯。

有序關聯容器setC++98唯一鍵集合,基于紅黑樹,自動排序。
mapC++98鍵值對集合(鍵唯一),基于紅黑樹,按鍵排序。
multisetC++98允許重復鍵的集合,基于紅黑樹。
multimapC++98允許重復鍵的鍵值對集合,基于紅黑樹。
無序關聯容器unordered_setC++11唯一鍵哈希集合,基于哈希表,元素無序。
unordered_mapC++11鍵值對哈希表(鍵唯一),基于哈希表。
unordered_multisetC++11允許重復鍵的哈希集合。
unordered_multimapC++11允許重復鍵的鍵值對哈希表。

容器適配器:通過限制接口實現特定數據結構(如棧、隊列、堆),底層依賴其他容器。

適配器stackC++98后進先出(LIFO)結構,默認基于std::deque實現。
queueC++98先進先出(FIFO)結構,默認基于std::deque實現。
priority_queueC++98優先級隊列(最大堆),默認基于std::vector實現。

?其他類容器類型:如std::stringstd::bitset,雖不是嚴格意義上的通用容器,但提供類似容器的操作。

其他類容器類型stringC++98字符串類,支持類似vector的操作。
bitsetC++98固定大小的位集合,用于位操作。
valarrayC++98數值計算專用數組,支持向量化操作。
spanC++20非擁有視圖,提供對連續內存的輕量訪問(如數組、vector等)。

鍵值對

鍵值對(Key-Value Pair)?是一種核心數據結構,用于將唯一的鍵(Key)?與對應的值(Value)?關聯,常用于快速查找、映射或配置管理。

  • 鍵(Key):唯一標識符,用于快速定位值(不可重復,除非使用?multimap)。

  • 值(Value):與鍵關聯的數據,可以是任意類型(基本類型、對象、容器等)。

鍵值對類型?std::pair

  • 定義std::pair<KeyType, ValueType>?是標準庫中表示鍵值對的模板類。

  • 訪問成員:通過?first(鍵)和?second(值)訪問。

pair<string, int> p("hello", 1);
cout << p.first << p.second << endl;
// hello1

set

set的概念

set?是一個有序關聯容器,存儲唯一鍵(Key),鍵本身即為其值(沒有額外的Value)。
元素按鍵的嚴格弱序規則(默認升序)自動排序,不允許重復鍵。

特性說明
唯一性所有元素唯一,插入重復值會被忽略(通過返回值可判斷是否插入成功)。
自動排序元素按鍵值自動排序(默認升序,可自定義排序規則)。
不可修改鍵元素(鍵)在容器中不可直接修改,需先刪除舊值再插入新值。
高效查找支持?O(log n)?復雜度的查找(find()count()?等操作)。
穩定迭代器插入或刪除操作不會使其他元素的迭代器失效(除非指向被刪除元素)。
  • set在底層是用平衡搜索樹(紅黑樹)實現的,所以在set當中查找某個元素的時間復雜度為 logN
  • set中的元素不能被修改,因為set在底層是用平衡搜索樹(紅黑樹)來實現的,若是對平衡搜索樹(紅黑樹)當中某個結點的值進行了修改,那么這棵樹將不再是平衡搜索樹(紅黑樹)

set的構造函數

1、默認構造函數:創建一個空的集合,可以指定自定義的比較器(Comparator)和分配器(Allocator)。

explicit set(const Compare& comp = Compare(), const Allocator& alloc = Allocator());set<int> s1; // 默認升序排序的空集合// 自定義降序排序的比較器
struct CompareDesc 
{bool operator()(int a, int b) const { return a > b; }
};
set<int, CompareDesc> s2; // 降序排列的空集合

2、范圍構造函數:通過迭代器范圍?[first, last)?初始化集合,元素會被自動去重并排序。

template <class InputIterator>
set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());vector<int> vec = {5, 2, 2, 3, 5};
// 從 vector 的迭代器范圍構造,自動去重并升序排序
std::set<int> s(vec.begin(), vec.end()); // s = {2, 3, 5}

?3、拷貝構造函數:創建一個新集合,復制另一個集合的所有元素。

set(const set& other);set<int> s_original = {1, 2, 3};
set<int> s_copy(s_original); // 深拷貝,s_copy = {1, 2, 3}

4、初始化列表構造函數(C++11 起):通過初始化列表(Initializer List)直接初始化集合。

set(std::initializer_list<value_type> init, const Compare& comp = Compare(), const Allocator& alloc = Allocator());set<int> s = {3, 1, 2, 2}; // 自動去重并排序為 {1, 2, 3}

set的使用

成員函數功能
insert插入指定元素
erase刪除指定元素
find查找指定元素
size獲取容器中元素的個數
empty判斷容器是否為空
clear清空容器
swap交換兩個容器中的數據
count獲取容器中指定元素值的元素個數

?示例:

#include <iostream>
#include <set>
#include <vector>
#include <algorithm> // 集合運算所需頭文件
using namespace std;// 自定義比較器(按字符串長度排序)
struct LengthCompare 
{bool operator()(const string& a, const string& b) const {return a.size() < b.size();}
};int main() 
{// ------------------------ 1. 初始化與插入 ------------------------set<int> s1 = {3, 1, 2, 2}; // 去重排序: {1, 2, 3}s1.insert(5);                // 插入5s1.emplace(4);               // 原地構造插入4// ------------------------ 2. 刪除與清空 ------------------------s1.erase(3);                 // 刪除元素3auto it = s1.find(1);if (it != s1.end()) s1.erase(it); // 通過迭代器刪除// s1.clear();               // 清空集合// ------------------------ 3. 遍歷與查找 ------------------------cout << "s1: ";for (int val : s1) {          // C++11 范圍for遍歷cout << val << " ";       // 輸出: 2 4 5}cout << endl;// 查找示例if (s1.count(4)) {cout << "4 exists in s1" << endl;}// ------------------------ 4. 自定義排序 ------------------------set<string, LengthCompare> s3 = {"apple", "banana", "cat"};// 按長度排序: "cat", "apple", "banana"cout << "s3: ";for (const auto& str : s3) {cout << str << " ";}cout << endl;return 0;
}

map

map的概念

  • 定義
    map?是一個有序關聯容器,存儲鍵值對(Key-Value Pair),其中鍵(Key)唯一,元素按鍵的嚴格弱序規則(默認升序)自動排序。
    每個元素是一個?std::pair<const Key, Value>,鍵不可修改,值可以修改。

  • 底層實現
    基于紅黑樹(Red-Black Tree,自平衡二叉搜索樹),保證插入、刪除和查找的時間復雜度為?O(log n)

特性說明
鍵唯一性所有鍵唯一,插入重復鍵會被忽略(可通過返回值判斷是否成功)。
自動排序元素按鍵自動排序(默認升序,可自定義排序規則)。
不可修改鍵鍵在容器中不可直接修改,需先刪除舊鍵值對再插入新鍵。
高效查找支持?O(log n)?復雜度的查找(find()count()?等操作)。
穩定迭代器插入或刪除操作不會使其他元素的迭代器失效(除非指向被刪除元素)。

map的構造函數

1、默認構造函數:創建一個空的?map,可指定自定義的比較器(Comparator)和分配器(Allocator)。

explicit map(const Compare& comp = Compare(), const Allocator& alloc = Allocator());map<int, string> m1; // 空map,默認按鍵升序排序// 自定義按字符串長度排序的比較器
struct KeyCompare {bool operator()(const string& a, const string& b) const {return a.size() < b.size();}
};
map<string, int, KeyCompare> m2; // 鍵按長度排序的空map

2、范圍構造函數:通過迭代器范圍?[first, last)?初始化?map,鍵值對會被自動去重并排序。

template <class InputIterator>
map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());vector<pair<int, string>> vec = {{3, "Alice"}, {1, "Bob"}, {3, "Charlie"}};// 從vector的迭代器構造,自動去重并按鍵升序排序
map<int, string> m3(vec.begin(), vec.end()); // {1: "Bob", 3: "Alice"}

3、拷貝構造函數:深拷貝另一個?map?的所有鍵值對。

map(const map& other);map<int, string> m_original = {{1, "A"}, {2, "B"}};
map<int, string> m_copy(m_original); // 深拷貝,m_copy = {1: "A", 2: "B"}

4、初始化列表構造函數(C++11 起):通過初始化列表直接初始化?map

map(initializer_list<value_type> init, const Compare& comp = Compare(), const Allocator& alloc = Allocator());map<int, string> m5 = {{3, "Alice"}, {1, "Bob"}, {3, "Charlie"}}; // 去重后 {1: "Bob", 3: "Alice"}// 自定義降序排序
map<int, string, greater<int>> m6 = {{3, "A"}, {1, "B"}}; // {3: "A", 1: "B"}

注意事項

  1. 鍵的唯一性:插入重復鍵時,insert?會失敗,operator[]?會覆蓋原有值。

  2. 自定義比較器:需滿足嚴格弱序規則(例如不能定義?<=?作為比較邏輯)。

  3. 性能權衡:若無需有序性,優先使用?unordered_map(哈希表實現,平均 O(1) 操作)。

map的使用

接口分類接口名稱作用
插入操作insert插入鍵值對,返回插入結果(迭代器 + 是否成功)。
emplace原地構造鍵值對,避免臨時對象拷貝。
operator[]通過鍵訪問值(若鍵不存在,插入默認值并返回引用)。
刪除操作erase刪除指定鍵或迭代器范圍內的鍵值對。
clear清空所有鍵值對。
查找與訪問find查找鍵,返回迭代器(未找到返回?end())。
count返回鍵的數量(0 或 1)。
contains?(C++20)檢查鍵是否存在,返回布爾值。
at安全訪問值(鍵不存在時拋出異常)。
容量查詢empty檢查容器是否為空。
size返回鍵值對數量。
迭代器begin?/?end獲取正向迭代器(按鍵升序)。
rbegin?/?rend獲取反向迭代器(按鍵降序)。

?示例:

#include <iostream>
#include <map>
#include <string>
using namespace std;int main() 
{map<int, string> m;// 插入操作m.insert({1, "Alice"});m.emplace(2, "Bob");      // 原地構造m[3] = "Charlie";         // operator[] 插入// 刪除操作m.erase(1);               // 刪除鍵1// m.clear();             // 清空所有元素// 查找與訪問auto it = m.find(3);if (it != m.end()) {cout << "鍵3的值: " << it->second << endl;}// operator[] 的副作用(自動插入默認值)cout << "m[4]: " << m[4] << endl; // 輸出空字符串(自動插入{4, ""})// 遍歷(C++17 結構化綁定)cout << "所有鍵值對:" << endl;for (const auto& [key, value] : m) {cout << key << ": " << value << endl;}// 容量查詢cout << "元素數量: " << m.size() << endl;cout << "是否為空: " << (m.empty() ? "是" : "否") << endl;return 0;
}

multiset

multiset容器與set容器的底層實現一樣,都是平衡搜索樹(紅黑樹),multiset容器和set容器的唯一區別就是,multiset允許鍵值冗余,即multiset容器當中存儲的元素是可以重復的。

特性std::setstd::multiset
鍵的唯一性鍵唯一,不允許重復允許重復鍵
插入操作插入重復鍵時失敗(返回?pair<iterator, bool>總是插入成功(返回?iterator
查找與計數count(key)?返回?0?或?1count(key)?可返回?>=0?的任意值
底層實現紅黑樹(自平衡二叉搜索樹)紅黑樹(自平衡二叉搜索樹)
時間復雜度插入、刪除、查找均為?O(log n)同?set
典型應用場景需要唯一鍵的有序集合(如用戶ID集合)允許重復的有序集合(如統計成績分布)
  • 選擇?set:需要保證鍵唯一性且需要有序遍歷的場景(如字典、配置表)。

  • 選擇?multiset:允許重復鍵且需要統計頻率或保留重復數據的場景(如日志時間戳記錄、投票統計)。

?

multimap

multimap容器與map容器的底層實現一樣,也都是平衡搜索樹(紅黑樹),multimap容器和map容器的區別,multimap允許鍵值冗余,即multimap容器當中存儲的元素是可以重復的

特性std::mapstd::multimap
鍵的唯一性鍵唯一,不允許重復允許重復鍵
插入操作插入重復鍵時覆蓋原有值(operator[])或失敗(insert總是插入成功,允許多個相同鍵的鍵值對共存
查找與訪問operator[]?直接通過鍵訪問值(鍵不存在時插入)沒有?operator[],必須通過迭代器訪問
查找結果find(key)?返回單個迭代器find(key)?返回第一個匹配鍵的迭代器
鍵值對數量每個鍵對應唯一值一個鍵可對應多個值
典型應用場景字典、配置表(鍵唯一)一對多映射(如學生ID對應多門課程成績)
  • 選擇?map:需要鍵唯一且直接通過鍵訪問值(如用戶ID到用戶名的映射)。

  • 選擇?multimap:允許鍵重復且需處理一對多關系(如訂單ID對應多個商品)。

  • 關鍵區別

    • map?的鍵唯一,支持?operator[]

    • multimap?允許鍵重復,需用迭代器或?equal_range?處理多個值。

?

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

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

相關文章

DeepSeek:構筑大數據平臺底座的最優解

一、大數據平臺底座的重要性 在數字化浪潮席卷全球的當下,數據已成為企業乃至整個社會最具價值的資產之一 。大數據平臺底座作為數據處理和業務支撐的核心樞紐,其重要性不言而喻,猶如大廈的基石,關乎整個數據生態系統的穩定與發展。 從數據處理角度來看,隨著互聯網、物聯…

Minix OS的配置 SSH C程序編譯

Minix3的下載 官網&#xff1a;https://www.minix3.org/ 安裝 平臺&#xff1a;VMware 開機后進入系統使用setup命令來配置和安裝盡量配置一個DNS服務器&#xff0c;比如8.8.8.8 SSH 安裝&#xff1a;pkgin install openssh 修改配置文件&#xff0c;需要&#xff1a; 修…

ubuntu20 安裝python2

1. 確保啟用了 Universe 倉庫 在某些情況下&#xff0c;python2-minimal 包可能位于 Universe 倉庫中。你可以通過以下命令啟用 Universe 倉庫并更新軟件包列表&#xff1a; bash復制 sudo add-apt-repository universe sudo apt update 然后嘗試安裝&#xff1a; bash復制…

STM32---FreeRTOS中斷管理試驗

一、實驗 實驗目的&#xff1a;學會使用FreeRTOS的中斷管理 創建兩個定時器&#xff0c;一個優先級為4&#xff0c;另一個優先級為6&#xff1b;注意&#xff1a;系統所管理的優先級范圍 &#xff1a;5~15 現象&#xff1a;兩個定時器每1s&#xff0c;打印一段字符串&#x…

docker利用docker-compose-gpu.yml啟動RAGFLOW,文檔解析出錯【親測已解決】

0.問題說明 想要讓RAGFLOW利用GPU資源跑起來&#xff0c;可以選擇docker-compose-gpu.yml啟動。&#xff08;但是官網啟動案例是86平臺的不是NVIDIA GPU的&#xff0c;docker-compose-gpu.yml又是第三方維護&#xff0c;所以稍有問題&#xff09; 1.問題 docker利用docker-c…

【AI深度學習網絡】卷積神經網絡(CNN)入門指南:從生物啟發的原理到現代架構演進

深度神經網絡系列文章 【AI深度學習網絡】卷積神經網絡&#xff08;CNN&#xff09;入門指南&#xff1a;從生物啟發的原理到現代架構演進【AI實踐】基于TensorFlow/Keras的CNN&#xff08;卷積神經網絡&#xff09;簡單實現&#xff1a;手寫數字識別的工程實踐 引言 在當今…

【ThreeJS Basics 06】Camera

文章目錄 Camera 相機PerspectiveCamera 透視相機正交相機用鼠標控制相機大幅度轉動&#xff08;可以看到后面&#xff09; 控制組件FlyControls 飛行組件控制FirstPersonControls 第一人稱控制PointerLockControls 指針鎖定控制OrbitControls 軌道控制TrackballControls 軌跡球…

Linux | Ubuntu 與 Windows 雙系統安裝 / 高頻故障 / UEFI 安全引導禁用

注&#xff1a;本文為 “buntu 與 Windows 雙系統及高頻故障解決” 相關文章合輯。 英文引文&#xff0c;機翻未校。 How to install Ubuntu 20.04 and dual boot alongside Windows 10 如何將 Ubuntu 20.04 和雙啟動與 Windows 10 一起安裝 Dave’s RoboShack Published in…

在 C++ 中,通常會使用 `#define` 來定義宏,并通過這種方式發出警告或提示。

在 C++ 中,通常會使用 #define 來定義宏,并通過這種方式發出警告或提示。 如何實現 GBB_DEPRECATED_MSG 宏: 你可以通過以下方式定義一個宏,顯示棄用警告: #include <iostream>// 定義一個宏,用來打印棄用警告 #define GBB_DEPRECATED_MSG(msg

el-tree右鍵節點動態位置展示菜單;el-tree的節點圖片動態根據節點屬性color改變背景色;加遮罩層(opacity)

一、el-tree右鍵節點動態位置展示菜單 關鍵:@node-contextmenu="handleRightClick"與@node-click=“handleNodeClick” <div class="content"><el-tabs class="tabs" @tab-click="handleClick" v-model="Modal"…

Leetcode 378-有序矩陣中第 K 小的元素

給你一個 n x n 矩陣 matrix &#xff0c;其中每行和每列元素均按升序排序&#xff0c;找到矩陣中第 k 小的元素。 請注意&#xff0c;它是 排序后 的第 k 小元素&#xff0c;而不是第 k 個 不同 的元素。 你必須找到一個內存復雜度優于 O(n2) 的解決方案。 示例 1&#xff1…

【二.提示詞工程與實戰應用篇】【3.Prompt調優:讓AI更懂你的需求】

最近老張在朋友圈秀出用AI生成的國風水墨畫,隔壁王姐用AI寫了份驚艷全場的年終總結,就連樓下小賣部老板都在用AI生成營銷文案。你看著自己跟AI對話時滿屏的"我不太明白您的意思",是不是懷疑自己買了臺假電腦?別慌,這可能是你的打開方式不對。今天咱們就聊聊這個…

UNIAPP前端配合thinkphp5后端通過高德API獲取當前城市天氣預報

如何通過 UniApp 前端項目與 ThinkPHP5 后端結合高德天氣 API 獲取天氣預報信息。我們將分為前端和后端兩部分進行實現。以下是一個完整的代碼. 一、項目結構 project/ ├── frontend/ (UniApp 項目) │ ├── pages/ │ │ └── weather/ │ │ ├── in…

藍橋杯C組真題——巧克力

題目如下 思路 代碼及解析如下 謝謝觀看

CSDN博客寫作教學(五):從寫作到個人IP的體系化構建(完結篇)

導語 (第一篇)Markdown編輯器基礎 (第二篇)Markdown核心語法 (第三篇)文章結構化思維 (第四篇)標題優化與SEO實戰 通過前四篇教程,你已掌握技術寫作的“術”——排版、標題、流量與數據。但真正的價值在于將技能升維為“道”:用技術博客為支點,撬動個人品牌與職業發…

Elasticsearch簡單學習

1、依賴的導入 <!--ES依賴--> <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>2、客戶端鏈接 RestHighLevelClient client new RestHigh…

macOS Sequoia 15.3 M3 Pro芯片 iOS 開發環境配置記錄(最新)

進行如下工作之前首先確保終端已翻墻&#xff0c;在ClashX選擇“復制終端代理命令”&#xff0c;在終端進行粘附并執行。 安裝 homebrew Homebrew 是 Mac 平臺的一個包管理工具&#xff0c;提供了許多Mac下沒有的Linux工具等。 /bin/bash -c "$(curl -fsSL https://raw…

迷你世界腳本組隊接口:Team

組隊接口&#xff1a;Team 彼得兔 更新時間: 2023-04-26 10:19:04 具體函數名及描述如下: 序號 函數名 函數描述 1 getNumTeam(...) 當前隊伍數量 2 getTeamPlayerNum(...) 獲取指定隊伍玩家數量 3 getTeamPlayers(...) 獲取指定隊伍玩家 4 random…

使用 Deepseek + kimi 快速生成PPT

前言 最近看到好多文章和視頻都在說&#xff0c;使用 Deepseek 和 kimi 能快速生成精美的 ppt&#xff0c;畢竟那都是別人說的&#xff0c;只有自己嘗試一次才知道結果。 具體操作 第一步&#xff1a;訪問 deepseek 我們訪問 deepseek &#xff0c;把我們想要輸入的內容告訴…

初始提示詞(Prompting)

理解LLM架構 在自然語言處理領域&#xff0c;LLM&#xff08;Large Memory Language Model&#xff0c;大型記憶語言模型&#xff09;架構代表了最前沿的技術。它結合了存儲和檢索外部知識的能力以及大規模語言模型的強大實力。 LLM架構由外部記憶模塊、注意力機制和語…