键值对容器
map 是基于红黑树实现的键值对容器,特点是:
#include <map>
using namespace std;
int main() {
// 创建 map
map mp;
// 插入元素
mp["apple"] = 5;
mp["banana"] = 3;
mp["cherry"] = 7;
// 插入的其他方式
mp.insert({"durian", 2});
mp.insert(make_pair("elderberry", 4));
// 访问元素
cout << mp["apple"] << endl; // 5
// 检查键是否存在
if (mp.find("banana") != mp.end()) {
cout << "找到 banana" << endl;
}
// count 返回 0 或 1
if (mp.count("fig")) {
cout << "存在 fig" << endl;
}
// 删除元素
mp.erase("apple");
// 遍历
for (auto& p : mp) {
cout << p.first << ": " << p.second << endl;
}
// 大小操作
cout << mp.size() << endl; // 4
cout << mp.empty() << endl; // false
mp.clear();
return 0;
}
map 存储键值对,按键自动排序:
map 为空
map mp = {
{1, "one"},
{3, "three"},
{5, "five"},
{7, "seven"},
{9, "nine"}
};
// 最小和最大键
cout << mp.begin()->first << endl; // 1
cout << mp.rbegin()->first << endl; // 9
// 大于等于某个键的第一个元素
auto it = mp.lower_bound(4);
// it 指向 {5, "five"}
// 大于某个键的第一个元素
it = mp.upper_bound(5);
// it 指向 {7, "seven"}
// 删除范围内的键值对
mp.erase(mp.lower_bound(3), mp.upper_bound(7));
// mp: {1, "one"}, {9, "nine"}
// 降序排列
map> mp = {
{1, "one"},
{3, "three"},
{2, "two"}
};
// mp: {3, "three"}, {2, "two"}, {1, "one"}
// 自定义比较函数
struct cmp {
bool operator()(string a, string b) const {
return a.length() < b.length(); // 按长度排序
}
};
map mp2;
mp2["apple"] = 1;
mp2["pear"] = 2;
mp2["banana"] = 3;
// mp2: {"pear", 2}, {"apple", 1}, {"banana", 3}
map mp;
// [] 操作符:不存在会自动创建默认值
int val = mp["apple"]; // mp["apple"] 被创建,值为 0
cout << val << endl; // 0
cout << mp["apple"] << endl; // 0
// 使用 at():不存在会抛出异常
try {
int val2 = mp.at("banana"); // 抛出异常
} catch (const out_of_range& e) {
cout << "键不存在" << endl;
}
// 查找后再访问
auto it = mp.find("banana");
if (it != mp.end()) {
cout << it->second << endl;
}
multimap 与 map 类似,但允许键重复。
#include <map>
using namespace std;
int main() {
multimap mm;
// 插入元素(允许重复键)
mm.insert({"apple", 1});
mm.insert({"banana", 2});
mm.insert({"apple", 3});
mm.insert({"apple", 4});
// count 返回键的出现次数
cout << mm.count("apple") << endl; // 3
// find 返回第一个匹配的迭代器
auto it = mm.find("apple"); // 指向第一个 apple
// 删除指定键的所有元素
mm.erase("apple");
// mm: {"banana", 2}
// 删除指定位置的元素
it = mm.find("banana");
mm.erase(it);
// mm: 空
// 遍历所有相同键的元素
mm.insert({"apple", 1});
mm.insert({"apple", 2});
mm.insert({"apple", 3});
auto range = mm.equal_range("apple");
for (auto it = range.first; it != range.second; it++) {
cout << it->first << ": " << it->second << endl;
}
// 输出:
// apple: 1
// apple: 2
// apple: 3
return 0;
}
map freq;
vector v = {1, 2, 2, 3, 3, 3, 4};
for (int x : v) {
freq[x]++;
}
for (auto& p : freq) {
cout << p.first << ": " << p.second << endl;
}
// 输出:
// 1: 1
// 2: 2
// 3: 3
// 4: 1
" << mp[x] << endl;
}
// 输出:
// 100 -> 2
// 50 -> 1
// 300 -> 4
// 50 -> 1
// 100 -> 2
// 200 -> 3
map mp = {{1, 10}, {3, 30}, {5, 50}, {7, 70}, {9, 90}};
// 查找键在 [3, 7] 范围内的所有键值对
auto start = mp.lower_bound(3);
auto end = mp.upper_bound(7);
for (auto it = start; it != end; it++) {
cout << it->first << ": " << it->second << endl;
}
// 输出:
// 3: 30
// 5: 50
// 7: 70
map mp = {{1, "one"}, {3, "three"}, {5, "five"}, {7, "seven"}};
// 查找键为4的前驱(小于4的最大键)
auto it = mp.lower_bound(4);
if (it != mp.begin()) {
it--; // 前驱
cout << "前驱: " << it->first << endl; // 3
}
// 查找键为4的后继(大于4的最小键)
it = mp.upper_bound(4);
if (it != mp.end()) {
cout << "后继: " << it->first << endl; // 5
}
| 操作 | map/multimap | unordered_map |
|---|---|---|
| 插入 | $$ O(\log n) $$ | $$ O(1) $$ |
| 删除 | $$ O(\log n) $$ | $$ O(1) $$ |
| 查找 | $$ O(\log n) $$ | $$ O(1) $$ |
| 区间查询 | $$ O(\log n) $$ | 不支持 |
| 顺序遍历 | 有序 | 无序 |