C++(10): std::map、std::multimap与std::unordered_map

1. 简述

        std::map、std::multimap 和 std::unordered_map 是 C++ 标准模板库(STL)中的三种关联容器,它们提供了存储键值对(pair)的方式,并允许通过键来快速检索值。这三者之间的主要区别在于它们的内部数据结构和对元素的排序方式。

2. std::map的特点

有序性:std::map 中的元素按照键的顺序存储,因此可以高效地进行中序遍历。

唯一性:每个键在 std::map 中都是唯一的,不允许重复的键存在。

性能:std::map 提供了对元素的高效查找、插入和删除操作,时间复杂度通常为 O(log n)。

内存消耗:由于使用平衡二叉搜索树,std::map 相比于 std::unordered_map 可能会有更高的内存消耗。

可预测性:由于元素的有序性,std::map 在迭代时提供了可预测的顺序,这在某些算法中非常有用。

3. std::map构造及其用法

(1)构造map

        首先需要引用头文件:#include <map>

        默认构造:

std::map<int, std::string> amap;

        使用初始化列表进行构造:

std::map<int, std::string> myMap = {  

    {1, "one"},  

    {2, "two"},  

    {3, "three"}  

};

        复制构造:

std::map<int, std::string> myMap1 = { {1, "one"}, {2, "two"} };

std::map<int, std::string> myMap2(myMap1);

(2)插入

        构造std::pair并插入:

amap.insert(std::pair<int, std::string>(5, “Derek”));

        使用make_pair(无需专门指定类型):

amap.insert(std::make_pair(5, “Derek”));

        使用amap的value_type构造插入:

amap.insert(std::map<int, std::string>::value_type(5, “Derek”));

        使用数组方式插入(注意,这种方式会覆盖原有已经存在的键值对):

amap.insert[1] = “Eaton”;

(3)删除元素

it = myMap.erase(it); // 删除迭代器指向的元素

        当使用迭代器删除元素以后,需要更新迭代器(原迭代器已经失效)。

myMap.erase(myMap.begin(), myMap.end()); // 删除所有元素

(4)查找元素

        std::map的元素查找可以使用find。

auto it = myMap.find(3);

if (it != myMap.end()) {

  // 找到元素

}

(5)访问元素

        可以使用下标或at访问元素。

std::string name = amap[2];

std::string name = amap.at(2);

        值得注意的是,使用at进行元素的访问过程中,如果元素不存在,则会报出std::out_of_range异常。

(6)获取大小

amap.size();

4. std::map例程

#include <iostream>

#include <map>


int main(int argc, char* argv[])

{

    /** 创建一个 std::map. */

    std::map<int, std::string> myMap;

    /** 插入键值对. */

    myMap.insert({1, "One"});

    myMap.insert({2, "Two"});

    myMap.insert({3, "Three"});

    /** 遍历 std::map. */

    for (const auto& pair : myMap) {

        std::cout << pair.first << ": " << pair.second << std::endl;

    }

    /** 访问元素. */

    std::cout << "The value for key 2 is: " << myMap[2] << std::endl;

    return 0;

}

5. std::multimap

        std::multimap 是 C++ 标准模板库中的一个关联容器,它类似于 std::map,但允许每个键关联多个值。std::multimap 基于平衡二叉搜索树实现,因此它保持了元素的有序性,按照键的顺序组织元素。

6. std::multimap的特点

键的多重性:与 std::map 不同,std::multimap 允许一个键对应多个值。

有序性:std::multimap 中的元素按照键的顺序存储,因此可以高效地进行中序遍历。

性能:std::multimap 提供了对元素的高效查找、插入和删除操作,时间复杂度通常为 O(log n)。

内存消耗:由于使用平衡二叉搜索树,std::multimap 相比于 std::unordered_multimap 可能会有更高的内存消耗。

7. std::multimap例程

#include <iostream>

#include <multimap>


int main(int argc, char* argv[])

{

    /** 创建一个 std::multimap. */

    std::multimap<int, std::string> myMultiMap;

    // 插入具有相同键的多个元素

    myMultiMap.insert({1, "One"});

    myMultiMap.insert({1, "Uno"});

    myMultiMap.insert({2, "Two"});

    myMultiMap.insert({3, "Three"});

    /** 遍历 std::multimap. */

    for (const auto& pair : myMultiMap) {

        std::cout << pair.first << ": " << pair.second << std::endl;

    }

    /** 查找具有特定键的所有元素. */

    auto range = myMultiMap.equal_range(1);

    std::cout << "Values for key 1: ";

    for (auto it = range.first; it != range.second; ++it) {

        std::cout << it->second << " ";

    }

    std::cout << std::endl;

    /** 访问特定键的第一个值. */

    std::string firstValue;

    auto it = myMultiMap.find(2);

    if (it != myMultiMap.end()) {

        firstValue = it->second;

    }

    std::cout << "The first value for key 2 is: " << firstValue << std::endl;

    /** 删除特定键的所有元素. */

    myMultiMap.erase(3);

    /** 再次遍历 std::multimap 确认元素已被删除. */

    std::cout << "Multimap after erasing key 3:" << std::endl;

    for (const auto& pair : myMultiMap) {

        std::cout << pair.first << ": " << pair.second << std::endl;

    }

    return 0;

}

8. unordered_map

        std::unordered_map 是一个基于哈希表的容器,它提供了最快的平均时间复杂度(通常是 O(1))来访问元素。与 std::map 和 std::multimap 不同,std::unordered_map 中的元素没有特定的顺序,元素的顺序取决于哈希函数和哈希表的内部结构。

9. std::unordered_map特点

无序性:std::unordered_map 中的元素不是按照键的顺序存储的,而是根据键的哈希值。

快速访问:由于使用了哈希表,std::unordered_map 通常能够提供接近常数时间复杂度(O(1))的查找、插入和删除操作。

内存消耗:相比于 std::map,std::unordered_map 可能会有更多的内存消耗,因为哈希表需要额外的空间来存储桶(buckets)和哈希值。

键的唯一性:std::unordered_map 中的键是唯一的,不允许有重复的键存在。

10. std::unordered_map例程

#include <iostream>

#include <unordered_map>


int main(int argc, char*argv[])

{

    /** 创建一个 std::unordered_map. */

    std::unordered_map<int, std::string> myUnorderedMap;

    /** 插入键值对. */

    myUnorderedMap.insert({1, "One"});

    myUnorderedMap.insert({2, "Two"});

    myUnorderedMap.insert({3, "Three"});

    /** 遍历 std::unordered_map. */

    for (const auto& pair : myUnorderedMap) {

        std::cout << pair.first << ": " << pair.second << std::endl;

    }

    /** 访问特定键的值. */

    std::string value = myUnorderedMap.at(2); ///< 抛出异常,如果键不存在

    /** 或者使用下标操作符,它返回一个默认值如果键不存在. */

    std::string value2 = myUnorderedMap[2];

    /** 查找元素. */

    auto it = myUnorderedMap.find(3);

    if (it != myUnorderedMap.end()) {

        std::cout << "The value for key 3 is: " << it->second << std::endl;

    }

    /** 删除元素. */

    myUnorderedMap.erase(it); ///< 删除迭代器指向的元素

    myUnorderedMap.erase(1); ///< 删除特定键的所有元素


    /** 再次遍历 std::unordered_map 确认元素已被删除. */

    std::cout << "Unordered map after erasing keys 1 and 3:" << std::endl;

    for (const auto& pair : myUnorderedMap) {

        std::cout << pair.first << ": " << pair.second << std::endl;

    }

    return 0;

}

要向`std::map<std::string,std::map<std::string,std::string>>`类型的`my_map`中插入数据,可以按照以下步骤进行操作: 1. 创建要插入的数据项,包括外层`std::string`类型的键和内层`std::map<std::string,std::string>`类型的值。例如,假设要插入的数据项为`key1 -> (inner_key1 -> value1, inner_key2 -> value2)`。 2. 使用`my_map[key1]`来访问外层`std::map`中的键`key1`对应的值,如果该键不存在,则会自动创建一个新的内层`std::map`。 3. 使用内层`std::map`的插入函数,例如`my_map[key1].insert(std::make_pair(inner_key1, value1))`,将内层键值对`(inner_key1, value1)`插入到对应的内层`std::map`中。 4. 重复上述步骤,插入其他内层键值对。 下面是一个示例代码,演示了如何向`my_map`中插入数据: ```cpp #include <iostream> #include <map> #include <string> int main() { std::map<std::string, std::map<std::string, std::string>> my_map; // 创建要插入的数据项 std::string key1 = "key1"; std::string inner_key1 = "inner_key1"; std::string value1 = "value1"; std::string inner_key2 = "inner_key2"; std::string value2 = "value2"; // 插入数据项 my_map[key1].insert(std::make_pair(inner_key1, value1)); my_map[key1].insert(std::make_pair(inner_key2, value2)); // 输出结果 for (const auto& outer_pair : my_map) { std::cout << outer_pair.first << " -> "; for (const auto& inner_pair : outer_pair.second) { std::cout << "(" << inner_pair.first << " -> " << inner_pair.second << ") "; } std::cout << std::endl; } return 0; } ``` 输出结果为: ``` key1 -> (inner_key1 -> value1) (inner_key2 -> value2) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值