C++ 各种map对比

特点比较

1. std::map
  • 底层实现:基于红黑树(一种自平衡的二叉搜索树)。
  • 元素顺序:元素按照键(key)的升序排列。
  • 键的唯一性:每个键只能出现一次,插入重复键的元素会被忽略。
  • 查找效率:查找操作的时间复杂度为 O ( l o g n ) O(log n) O(logn),其中 n n n 是容器中元素的数量。
  • 插入和删除效率:插入和删除操作的时间复杂度也为 O ( l o g n ) O(log n) O(logn)
2. std::unordered_map
  • 底层实现:基于哈希表。
  • 元素顺序:元素没有特定的顺序,存储位置由键的哈希值决定。
  • 键的唯一性:每个键只能出现一次,插入重复键的元素会覆盖原有的元素。
  • 查找效率:平均情况下,查找操作的时间复杂度为 O ( 1 ) O(1) O(1),但在最坏情况下可能达到 O ( n ) O(n) O(n)
  • 插入和删除效率:平均情况下,插入和删除操作的时间复杂度为 O ( 1 ) O(1) O(1)
3. std::multimap
  • 底层实现:同样基于红黑树。
  • 元素顺序:元素按照键的升序排列。
  • 键的唯一性:允许键重复,即可以有多个元素具有相同的键。
  • 查找效率:查找操作的时间复杂度为 O ( l o g n ) O(log n) O(logn)
  • 插入和删除效率:插入和删除操作的时间复杂度为 O ( l o g n ) O(log n) O(logn)
4. std::unordered_multimap
  • 底层实现:基于哈希表。
  • 元素顺序:元素没有特定的顺序,由键的哈希值决定存储位置。
  • 键的唯一性:允许键重复。
  • 查找效率:平均情况下,查找操作的时间复杂度为 O ( 1 ) O(1) O(1),最坏情况下为 O ( n ) O(n) O(n)
  • 插入和删除效率:平均情况下,插入和删除操作的时间复杂度为 O ( 1 ) O(1) O(1)
5. hash_map(SGI STL 扩展)
  • 底层实现:基于哈希表。
  • 元素顺序:元素没有特定的顺序,由键的哈希值决定存储位置。
  • 键的唯一性:每个键只能出现一次,插入重复键的元素会覆盖原有的元素。
  • 查找效率:平均情况下,查找操作的时间复杂度为 O ( 1 ) O(1) O(1),最坏情况下为 O ( n ) O(n) O(n)
  • 插入和删除效率:平均情况下,插入和删除操作的时间复杂度为 O ( 1 ) O(1) O(1)
    在早期的 C++ 标准(如 C++98、C++03)中有 hash_map,不过它并非标准库的一部分,而是来自于 SGI STL 扩展。在 C++11 及以后的标准中,hash_mapstd::unordered_map 替代,std::unordered_map 成为标准的哈希表实现。不过有些编译器仍然支持 hash_map,下面为你加入 hash_map 并进行比较,同时给出相应的 C++ 示例代码。

C++ 示例代码

#include <iostream>
#include <map>
#include <unordered_map>
#include <ext/hash_map>  // 对于支持 hash_map 的编译器

// 演示 std::map 的使用
void testStdMap() {
    std::map<int, std::string> myMap;
    myMap[1] = "apple";
    myMap[2] = "banana";
    myMap[1] = "cherry";  // 键 1 重复,会覆盖原有的值

    std::cout << "std::map:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
}

// 演示 std::unordered_map 的使用
void testUnorderedMap() {
    std::unordered_map<int, std::string> myUnorderedMap;
    myUnorderedMap[1] = "apple";
    myUnorderedMap[2] = "banana";
    myUnorderedMap[1] = "cherry";  // 键 1 重复,会覆盖原有的值

    std::cout << "\nstd::unordered_map:" << std::endl;
    for (const auto& pair : myUnorderedMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
}

// 演示 std::multimap 的使用
void testMultiMap() {
    std::multimap<int, std::string> myMultiMap;
    myMultiMap.insert({1, "apple"});
    myMultiMap.insert({2, "banana"});
    myMultiMap.insert({1, "cherry"});  // 键 1 重复,允许插入

    std::cout << "\nstd::multimap:" << std::endl;
    for (const auto& pair : myMultiMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
}

// 演示 std::unordered_multimap 的使用
void testUnorderedMultiMap() {
    std::unordered_multimap<int, std::string> myUnorderedMultiMap;
    myUnorderedMultiMap.insert({1, "apple"});
    myUnorderedMultiMap.insert({2, "banana"});
    myUnorderedMultiMap.insert({1, "cherry"});  // 键 1 重复,允许插入

    std::cout << "\nstd::unordered_multimap:" << std::endl;
    for (const auto& pair : myUnorderedMultiMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
}

// 演示 hash_map 的使用
void testHashMap() {
    __gnu_cxx::hash_map<int, std::string> myHashMap;
    myHashMap[1] = "apple";
    myHashMap[2] = "banana";
    myHashMap[1] = "cherry";  // 键 1 重复,会覆盖原有的值

    std::cout << "\nhash_map:" << std::endl;
    for (const auto& pair : myHashMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
}

int main() {
    testStdMap();
    testUnorderedMap();
    testMultiMap();
    testUnorderedMultiMap();
    testHashMap();

    return 0;
}

代码解释

  • testStdMap 函数演示了 std::map 的使用,插入重复键的元素会覆盖原有的值,元素按照键的升序排列。
  • testUnorderedMap 函数演示了 std::unordered_map 的使用,插入重复键的元素也会覆盖原有的值,元素没有特定的顺序。
  • testMultiMap 函数演示了 std::multimap 的使用,允许插入重复键的元素,元素按照键的升序排列。
  • testUnorderedMultiMap 函数演示了 std::unordered_multimap 的使用,允许插入重复键的元素,元素没有特定的顺序。
  • testHashMap 函数演示了 hash_map 的使用,插入重复键的元素会覆盖原有的值,元素没有特定的顺序。

需要注意的是,hash_map 不是标准 C++ 的一部分,如果你使用的编译器不支持 ext/hash_map 头文件,代码可能无法编译。建议优先使用标准的 std::unordered_map

### C++ 中 `set` 和 `map` 的用法与区别 #### 定义与基本特性 在 C++ 标准模板库(STL)中,`std::set` 是一种关联容器,用于存储唯一的键值并自动保持有序排列[^3]。而 `std::map` 则是一种键值对的集合,其中每个键都唯一,并且会按照键的顺序进行排序[^4]。 #### 数据结构基础 - **Set**: 基于平衡二叉树实现(通常是红黑树),因此其内部元素始终处于升序或降序状态。它不允许重复元素存在。 - **Map**: 同样基于平衡二叉树实现,但它的节点由一对 key-value 组成。Key 部分负责排序,Value 存储数据。 #### 主要功能对比 | 特性 | Set | Map | |--------------|------------------------------|-----------------------------| | **用途** | 仅保存不重复的关键字 | 关联关键字与其对应的值 | | **插入操作** | 插入单个元素 | 插入键值对 | | **查找效率** | 对数时间复杂度 O(log n) | 对数时间复杂度 O(log n) | | **删除操作** | 删除指定元素 | 删除特定键及其对应值 | #### 使用示例代码 以下是关于如何使用 `set` 和 `map` 的简单例子: ```cpp #include <iostream> #include <set> #include <map> int main() { std::set<int> my_set; my_set.insert(10); my_set.insert(20); for(auto it = my_set.begin(); it != my_set.end(); ++it){ std::cout << *it << '\n'; } std::map<std::string, int> my_map; my_map["apple"] = 1; my_map["banana"] = 2; for(auto const& pair : my_map){ std::cout << pair.first << ": " << pair.second << '\n'; } } ``` 上述程序展示了向 `set` 添加整型数值以及遍历它们的方法;同时也演示了怎样往 `map` 加入字符串作为key、整数作为value的过程,并打印这些键值对[^5]。 #### 性能考量 由于两者均采用自平衡二叉搜索树来组织内部数据项,所以对于大多数标准操作——比如插入(insert),移除(erase), 查找(find)—的时间成本都是O(log N)[^6]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值