Map

map 简介

Map(映射)是一种可以使用任何类型的数据作为索引的表格**。因此,Map 是数组的一种泛化,因为数组只能使用有序类型(如字符和非负整数)的常量和变量进行索引,而不能使用字符串或双精度浮点数。

Map 使用键(key)作为索引,并存储可以通过这些键访问的元素(element)。与数组中的索引类似,Map 中的键是唯一的,即一个键只与一个元素关联。因此,Map 也是集合(set)的一种泛化。

像集合一样,Map 通常是使用红黑树(red-black trees)实现的。与仅存储元素的集合不同,实现 Map 的树存储的是键值对(pair)<key, element>。这些键值对是根据键的排序函数进行排序的,而不是根据元素进行排序。因此,可以通过使用与所需元素关联的键来定位树中的特定节点,并提取存储在该节点的键值对的第二个元素(即元素本身)来找到特定的元素。

与集合不同的是,Map 中的元素是可以被修改的,因为树是根据键排序的,而不是根据元素排序的。这也意味着 Map 中的键不能被修改

简单来说,Map 是一种数据结构,它可以让你使用一个唯一的键来快速查找、访问和修改与之关联的值。它的底层实现通常基于高效的平衡二叉搜索树(如红黑树),这使得查找、插入和删除操作通常具有较高的效率。

你可以将 Map 想象成一个电话簿,人名是唯一的键,而电话号码是与之关联的元素。你可以通过人名(键)快速找到对应的电话号码(元素)。

map 成员函数

成员函数 描述
insert(const pair<const K, V>& val) 将键值对 val 插入到 map 中。如果键已存在,则不进行插入。返回一个 pair<iterator, bool>,其中迭代器指向插入的元素(或已存在的元素),bool 值指示是否成功插入。
insert(iterator position, const pair<const K, V>& val) 在迭代器 position 指示的位置之前插入键值对 val。提示:此操作对 map 的排序影响不大,主要用于提示插入位置,返回值是指向插入元素的迭代器。
insert(iterator first, iterator last) 插入由迭代器 firstlast 指示范围内的键值对。
erase(const K& key) 从 map 中移除所有键等于 key 的元素。返回移除的元素个数(对于 map 来说,结果要么是 0,要么是 1)。
erase(iterator position) 移除迭代器 position 指向的元素。
erase(iterator first, iterator last) 移除范围 [first, last) 内的所有元素。
clear() 移除 map 中的所有元素。
find(const K& key) const 返回一个指向 map 中第一个键等于 key 的元素的迭代器。如果未找到,则返回 end()
count(const K& key) const 返回 map 中键等于 key 的元素个数(对于 map 来说,结果要么是 0,要么是 1)。
empty() const 如果 map 为空,则返回 true,否则返回 false
size() const 返回 map 中元素的个数。
begin() const 返回指向 map 中第一个元素的迭代器。
end() const 返回指向 map 中最后一个元素之后位置的迭代器。
rbegin() const 返回指向 map 中最后一个元素的逆向迭代器。
rend() const 返回指向 map 中第一个元素之前位置的逆向迭代器。
lower_bound(const K& key) const 返回一个指向 map 中第一个键不小于 key 的元素的迭代器。
upper_bound(const K& key) const 返回一个指向 map 中第一个键大于 key 的元素的迭代器。
equal_range(const K& key) const 返回一个 pair<iterator, iterator>,表示 map 中所有键等于 key 的元素的范围。
operator[](const K& key) 如果键 key 存在,则返回对其关联值的引用。如果键不存在,则插入一个新的键值对,使用默认构造函数创建值,并返回对其关联值的引用。
swap(map& other) 将当前 map 的内容与另一个 map other 的内容进行交换。
key_comp() const 返回比较 map 中键的比较函数对象。
value_comp() const 返回比较 map 中值的比较函数对象。

map DEMO程序

#include <iostream>
#include <map>
#include <string>
#include <iterator>

using namespace std;

int main() {
    // 创建一个存储字符串键和整数值的 map
    map<string, int> myMap;

    // 插入元素
    myMap.insert(pair<string, int>("apple", 1));
    myMap.insert(make_pair("banana", 2));
    myMap["cherry"] = 3; // 使用 operator[] 插入或修改元素
    myMap["apple"] = 4;  // 修改已存在键的值

    cout << "Map 中的元素 (按键升序):" << endl;
    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl;
    }
    cout << endl;

    // 检查 map 是否为空
    if (myMap.empty()) {
        cout << "Map 是空的" << endl;
    } else {
        cout << "Map 不是空的,包含 " << myMap.size() << " 个元素" << endl;
    }
    cout << endl;

    // 查找元素
    string searchKey = "banana";
    auto it = myMap.find(searchKey);
    if (it != myMap.end()) {
        cout << "找到键为 '" << searchKey << "' 的元素,值为: " << it->second << endl;
    } else {
        cout << "未找到键为 '" << searchKey << "' 的元素" << endl;
    }
    cout << endl;

    // 统计键的个数
    string countKey = "apple";
    cout << "键为 '" << countKey << "' 的元素在 map 中出现了 " << myMap.count(countKey) << " 次" << endl;
    cout << endl;

    // 删除元素
    string eraseKey = "cherry";
    myMap.erase(eraseKey);
    cout << "移除键为 '" << eraseKey << "' 的元素后,Map 中的元素:" << endl;
    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl;
    }
    cout << endl;

    // 使用迭代器删除元素
    auto itToDelete = myMap.find("banana");
    if (itToDelete != myMap.end()) {
        myMap.erase(itToDelete);
        cout << "移除键为 'banana' 的元素后,Map 中的元素:" << endl;
        for (const auto& pair : myMap) {
            cout << pair.first << ": " << pair.second << endl;
        }
        cout << endl;
    }

    // 使用 lower_bound 和 upper_bound
    cout << "第一个键不小于 'grape' 的元素是: " << myMap.lower_bound("grape")->first << ": " << myMap.lower_bound("grape")->second << endl;
    cout << "第一个键大于 'grape' 的元素是: " << myMap.upper_bound("grape")->first << ": " << myMap.upper_bound("grape")->second << endl;
    cout << endl;

    // 清空 map
    myMap.clear();
    cout << "清空 Map 后的大小: " << myMap.size() << endl;

    return 0;
}