C++ STL 中的 Map(键值对)
Map 是关联容器,以 键-值对(key-value) 的形式按 键排序 存储数据。它基于 自平衡二叉搜索树(具体为 红黑树),因此具备以下特性:
- 查找、插入、删除的时间复杂度均为 O(log n)。
- 自动禁止 重复键。
- 键按 升序 排列。
- 与
unordered_map相比,map的搜索、插入、删除稍慢,但能获得 有序结果,并支持upper_bound()、lower_bound()等额外操作。
#include <iostream>
#include <map>
using namespace std;
int main() {
// 创建空 map
map<int, string> m1;
// 使用初始化列表创建 map
map<int, string> m2 = {
{1, "Geeks"},
{2, "For"},
{3, "Geeks"}
};
// 遍历并打印
for (auto& p : m2){
cout << p.first << " " << p.second << endl;
}
return 0;
}
1 Geeks
2 For
3 Geeks
语法
map 容器在头文件 <map> 中被定义为 std::map 类模板。
map<键, 值> m;
其中:
键类型:键(key)的数据类型。值类型:值(value)的数据类型。m:给 map 起的名字。
基本操作
下文展示 map 容器的基础操作:
1.插入元素
insert() 用于向 map 新增键值对。
- 只有当 键尚不存在 时才会成功插入;
- 若键已存在,
insert()不会更新原值,map 保持不变。 插入时间复杂度:O(log n)。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, string> m = { {2, "For"}, {3, "Geeks"} };
// 插入一对新键值
m.insert({1, "Geeks"});
for (auto x : m){
cout << x.first << " " << x.second << endl;
}
return 0;
}
1 Geeks
2 For
3 Geeks
2.访问元素
可以使用 [] 运算符访问元素,它根据给定的键返回值;
(1)若该键不存在,
[]会自动插入该键,并将其值设为默认值。
(2)若想仅检查键是否存在而不插入,可使用find()。
按键访问的时间复杂度:O(log n)。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, string> m = {
{1, "Geeks"},
{2, "For"},
{3, "Geeks"}
};
// 访问元素
cout << m[1] << endl; // 使用 []
cout << m.at(2); // 使用 at()
return 0;
}
Geeks
For
3.更新元素
要更新某个键对应的值,只需使用 map[key] = 新值 即可。
若该键已存在,其值会被更新;若不存在,会新建该键值对。也可使用 at() 进行更新(但键必须已存在,否则会抛出异常)。
更新操作的时间复杂度:O(log n)。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, string> m = {
{1, "Geeks"},
{2, "For"},
{3, "Geeks"}
};
// 更新值
m[0] = "Tweaks"; // 插入新键 0
m.at(1) = "By"; // 更新键 1 的值
cout << m[0] << endl;
cout << m.at(1);
return 0;
}
Tweaks
By
4.查找元素
find() 函数用于检查某个键是否存在于 map 中。
- 若找到,返回指向该键值对的迭代器;
- 若未找到,返回
end(),表示“不存在”。
查找时间复杂度:O(log n)。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, string> m = {
{1, "Geeks"},
{2, "For"},
{3, "Geeks"}
};
// 查找键为 2 的元素
auto it = m.find(2);
if (it != m.end())
cout << it->first << " " << it->second;
else
cout << "未找到该键!";
return 0;
}
2 For
5.遍历
可以使用循环遍历 map 中的所有键值对,访问顺序按键的升序排列。
遍历时间复杂度:O(n)。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, string> m = {
{1, "Geeks"},
{2, "For"},
{3, "Geeks"}
};
// 使用迭代器遍历
for (auto it = m.begin(); it != m.end(); ++it){
cout << it->first << " " << it->second << endl;
}
return 0;
}
1 Geeks
2 For
3 Geeks
6.删除元素
要从 map 中删除某个键及其对应的值,可使用 erase(key);
若该键存在,则删除整对键值,否则不做任何操作。
也可传入迭代器删除指定位置。
删除时间复杂度:O(log n)。
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, string> m = {
{1, "Geeks"},
{2, "For"},
{3, "Geeks"}
};
// 按键删除
m.erase(2);
// 按迭代器删除
m.erase(m.begin());
for (auto i : m)
cout << i.first << " " << i.second << endl;
return 0;
}
3 Geeks
C++ STL 中的 Set(集合)
Set 是一个容器,用于存储不重复的元素,并按一定顺序排列。 它基于自平衡二叉搜索树(具体为红黑树),因此具备以下特性:
- 查找、插入、删除的时间复杂度均为 O(log n)。
- 不允许重复元素。
- 默认按升序排列,也可通过自定义比较器指定排序规则。
- 与
unordered_set相比,操作稍慢,但能得到有序序列,并支持upper_bound()、lower_bound()等额外功能。
#include <iostream>
#include <set>
using namespace std;
int main() {
// 创建空集合
set<int> s1;
// 使用初始化列表创建集合(重复值会被自动去重)
set<int> s2 = {1, 2, 3, 2, 1};
// 遍历集合
for (auto& x : s2){
cout << x << " ";
}
cout << endl;
return 0;
}
1 2 3
语法
set 容器在头文件 <set> 中被定义为 std::set 类模板。
set<元素类型> s;
其中:
- 元素类型:集合中元素的数据类型。
- s:给集合起的名字。
基本操作
下面展示 set 容器的常用操作:
1.插入元素
insert() 仅当元素尚不存在时才将其加入集合;若元素已存在,insert() 什么也不做(集合不允许重复)。
#include <iostream>
#include <set>
using namespace std;
int main() {
// 用初始值构造集合
set<int> s = {2, 3};
// 插入新元素
s.insert(1);
// 遍历集合
for (auto x : s)
cout << x << endl;
return 0;
}
1
2
3
2.查找元素
find()用于检查某个元素是否存在:- 若找到,返回指向该元素的迭代器;
- 若未找到,返回
end()。
count()也可用来判断存在性:存在返回 1,不存在返回 0。
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s = {1, 2, 3};
// 使用 find() 查找
auto it = s.find(1);
if (it != s.end())
cout << "找到元素: " << *it << endl;
// 使用 count() 判断存在
if (s.count(2))
cout << "2 存在于集合中" << endl;
// 遍历输出所有元素
cout << "所有元素: ";
for (auto x : s)
cout << x << " ";
cout << endl;
return 0;
}
找到元素: 1
2 存在于集合中
所有元素: 1 2 3
3.遍历
可以使用循环(如范围 for 或迭代器)遍历集合中的所有元素。 遍历顺序即为元素在集合中的有序顺序(默认升序,或按自定义比较器)。
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s = {1, 2, 3};
// 使用迭代器遍历
for (auto it = s.begin(); it != s.end(); ++it)
cout << *it << endl;
return 0;
}
1
2
3
4.删除元素
使用 erase() 可从集合中删除指定元素:
- 若元素存在,则删除;
- 若不存在,什么也不做。
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s = {1, 2, 3, 4};
// 按值删除
s.erase(2);
// 按迭代器删除
s.erase(s.begin());
// 遍历集合
for (auto i : s)
cout << i << " ";
cout << endl;
return 0;
}
3 4