跳到主要内容C++ STL 容器 set 与 map 使用详解 | 极客日志C++算法
C++ STL 容器 set 与 map 使用详解
综述由AI生成C++ STL 中 set、multiset、map、multimap 及 pair 容器的核心特性与常用操作。涵盖容器构造、元素增删改查、迭代器遍历、比较规则自定义等内容。通过代码示例演示了去重排序、键值对映射、区间查找等应用场景,并结合 LeetCode 题目展示了在实际算法问题中的使用方法。
ApiHolic21 浏览 概述
C++ 标准模板库(STL)提供了丰富的容器类型,主要分为序列式容器和关联式容器。
序列容器和关联容器
序列式容器
- 逻辑结构:线性序列(数组、链表等)
- 元素关联:仅通过位置的顺序关联
- 访问依据:存储位置(索引或迭代器)
- 典型实现:
vector、list、deque
关联式容器
- 逻辑结构:非线性结构(树、哈希表等)
- 元素关联:通过键值的有序或哈希的映射关联
- 访问依据:关键字(Key)
- 典型实现:
set、map、unordered_set、unordered_map
set 容器
1. 介绍
std::set 是关联容器,底层通常由红黑树实现。它存储唯一且排序的元素。
template<class T,
class Compare = less<T>,
class Alloc = allocator<T>
>
class set;
模板参数说明:
- 元素类型(T):set 底层存储的关键字类型,需保证该类型支持比较操作。
- 比较器(Compare):用于定义元素间的排序规则。
- 内存分配器(Allocator):负责管理 set 的内存分配与释放。
2. 常见构造
#include <iostream>
#include <set>
int main() {
std::set<int> s1;
myints[] = {, , , , };
;
;
{
{
lhs < rhs;
}
};
std::set<, classcomp> s5;
;
}
int
10
20
30
40
50
std::set<int> s2(myints, myints + 5)
std::set<int> s3(s2)
struct
classcomp
bool operator()(const int& lhs, const int& rhs) const
return
int
return
0
3. 常用操作
容量操作
size():返回元素个数。
empty():判断是否为空。
std::set<int> myset;
myset.insert(10);
std::cout << "Size: " << myset.size() << '\n';
if (myset.empty()) {
std::cout << "Empty" << '\n';
} else {
std::cout << "Not Empty" << '\n';
}
修改操作
clear():清空容器。
swap():交换两个容器的内容。
insert():插入元素。
erase():删除元素。
myset.insert(20);
auto ret = myset.insert(30);
myset.erase(20);
myset.erase(it);
myset.erase(it1, it2);
查找操作
find():查找元素。
count():统计元素出现次数(set 中为 0 或 1)。
lower_bound() / upper_bound():二分查找边界。
equal_range():返回指定元素的上下界范围。
auto it = myset.find(20);
if (it != myset.end()) {
std::cout << *it << '\n';
}
auto range = myset.equal_range(20);
4. 使用示例
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s = {5, 2, 7, 2, 8};
set<int, greater<int>> s_desc;
s_desc.insert(10);
s_desc.insert(5);
for (auto e : s) {
cout << e << " ";
}
return 0;
}
multiset 容器
1. 介绍
std::multiset 与 set 类似,但允许重复元素。
2. 区别
| 特性 | set | multiset |
|---|
| 元素唯一性 | 唯一 | 可重复 |
| count 返回值 | 0 或 1 | 实际数量 |
| erase(key) | 删除一个 | 删除所有匹配 |
#include <iostream>
#include <set>
using namespace std;
int main() {
multiset<int> ms = {4, 2, 4, 8, 4};
cout << ms.count(4) << endl;
ms.erase(4);
return 0;
}
pair 类模板
1. 介绍
std::pair 将两个不同类型的数据组合成一个逻辑单元。
#include <utility>
std::pair<int, string> p(1, "hello");
p.first = 2;
p.second = "world";
2. 使用
typedef pair<const Key, T> value_type;
auto p = make_pair(1, "test");
map 容器
1. 介绍
std::map 存储键值对(Key-Value),按键排序,键唯一。
template<class Key,
class T,
class Compare = less<Key>,
class Alloc = allocator<pair<const Key, T>>
>
class map;
2. 常用操作
operator[]:访问或插入键值对。
find():查找键。
insert():插入键值对。
erase():删除元素。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, int> m;
m["apple"] = 5;
m["banana"] = 3;
if (m.count("apple")) {
cout << "Found apple" << endl;
}
auto it = m.find("banana");
if (it != m.end()) {
it->second = 10;
}
return 0;
}
3. 使用示例
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
string arr[] = {"apple", "banana", "apple"};
map<string, int> countMap;
for (const auto& str : arr) {
countMap[str]++;
}
for (const auto& e : countMap) {
cout << e.first << ": " << e.second << endl;
}
return 0;
}
multimap 容器
1. 介绍
std::multimap 允许键重复,适用于一对多映射关系。
2. 区别
map:键唯一,不支持 operator[] 的多值场景。
multimap:键可重复,不支持 operator[](因无法明确指定哪个值)。
OJ 练习
1. 两个数组的交集
题目描述:给定两个整数数组,返回它们的交集,结果中每个元素必须是唯一的。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> s1(nums1.begin(), nums1.end());
set<int> s2(nums2.begin(), nums2.end());
vector<int> ret;
auto it1 = s1.begin();
auto it2 = s2.begin();
while (it1 != s1.end() && it2 != s2.end()) {
if (*it1 < *it2) {
it1++;
} else if (*it1 > *it2) {
it2++;
} else {
ret.push_back(*it1);
it1++;
it2++;
}
}
return ret;
}
};
2. 环形链表 II
题目描述:检测链表中是否有环,并返回环的入口节点。
class Solution {
public:
ListNode* detectCycle(ListNode* head) {
set<ListNode*> visited;
ListNode* cur = head;
while (cur) {
if (!visited.insert(cur).second) {
return cur;
}
cur = cur->next;
}
return nullptr;
}
};
3. 随机链表的复制
class Solution {
public:
Node* copyRandomList(Node* head) {
map<Node*, Node*> m;
Node* copyHead = nullptr;
Node* copyTail = nullptr;
Node* curr = head;
while (curr) {
if (!copyTail) {
copyHead = copyTail = new Node(curr->val);
} else {
copyTail->next = new Node(curr->val);
copyTail = copyTail->next;
}
m[curr] = copyTail;
curr = curr->next;
}
curr = head;
Node* copy = copyHead;
while (curr) {
if (curr->random) {
copy->random = m[curr->random];
}
curr = curr->next;
copy = copy->next;
}
return copyHead;
}
};
4. 前 K 个高频单词
思路:利用 map 统计频率,结合 sort 或 priority_queue 排序。
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
map<string, int> m;
for (const auto& w : words) {
m[w]++;
}
vector<pair<string, int>> v(m.begin(), m.end());
sort(v.begin(), v.end(), [](const pair<string, int>& a, const pair<string, int>& b) {
if (a.second != b.second) return a.second > b.second;
return a.first < b.first;
});
vector<string> ret;
for (int i = 0; i < k; ++i) {
ret.push_back(v[i].first);
}
return ret;
}
};
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online