面试题:C++ 中 map 和 unordered_map 的区别?分别在什么场景下使用?

在 C++ 中,std::map 和 std::unordered_map 是两种常用的关联容器,用于存储键值对。它们的核心区别在于底层实现和性能特性,因此适用于不同的场景。


1. std::map

  • 底层实现:基于红黑树(一种平衡二叉搜索树)。
  • 特性
    • 元素按键的顺序存储(默认按升序排列)。
    • 插入、删除和查找操作的时间复杂度为 O(log n)
    • 支持范围查询(如查找某个范围内的键)。
    • 内存占用较高(需要存储树结构的相关信息)。
  • 使用场景
    • 需要元素按键排序的场景。
    • 需要频繁进行范围查询的场景。
    • 对性能要求不是特别高,但需要稳定性能的场景。

示例:

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> m;
    m["apple"] = 3;
    m["banana"] = 5;
    m["cherry"] = 2;

    // 元素按键排序
    for (const auto& pair : m) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
    return 0;
}

输出:

apple: 3
banana: 5
cherry: 2

2. std::unordered_map

  • 底层实现:基于哈希表。
  • 特性
    • 元素无序存储(顺序取决于哈希函数)。
    • 插入、删除和查找操作的平均时间复杂度为 O(1),最坏情况下为 O(n)(哈希冲突严重时)。
    • 不支持范围查询。
    • 内存占用较低(哈希表的开销较小)。
  • 使用场景
    • 需要快速查找、插入和删除的场景。
    • 不需要元素按键排序的场景。
    • 对性能要求较高的场景。

示例:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> um;
    um["apple"] = 3;
    um["banana"] = 5;
    um["cherry"] = 2;

    // 元素无序存储
    for (const auto& pair : um) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
    return 0;
}

输出:

cherry: 2
banana: 5
apple: 3

3. 关键区别

特性std::mapstd::unordered_map
底层实现红黑树(平衡二叉搜索树)哈希表
元素顺序按键排序无序
插入/删除/查找O(log n)平均 O(1),最坏 O(n)
范围查询支持不支持
内存占用较高较低
适用场景需要排序或范围查询需要快速查找、插入和删除

4. 使用场景对比

(1)std::map 的使用场景

  • 需要元素按键排序
    • 例如,存储学生成绩并按姓名排序。
  • 需要范围查询
    • 例如,查找分数在 80 到 90 之间的学生。
  • 对性能要求不是特别高
    • 例如,数据量较小或操作频率较低的场景。

(2)std::unordered_map 的使用场景

  • 需要快速查找、插入和删除
    • 例如,缓存系统或字典查找。
  • 不需要元素按键排序
    • 例如,存储用户会话信息。
  • 对性能要求较高
    • 例如,数据量较大或操作频率较高的场景。

5. 性能对比

  • 查找性能
    • std::unordered_map 的平均查找性能优于 std::map,但在哈希冲突严重时性能会下降。
  • 插入和删除性能
    • std::unordered_map 的平均性能优于 std::map
  • 内存占用
    • std::unordered_map 的内存占用通常低于 std::map

6. 总结

  • std::map
    • 适用于需要元素排序或范围查询的场景。
    • 性能稳定,但不如 std::unordered_map 高效。
  • std::unordered_map
    • 适用于需要快速查找、插入和删除的场景。
    • 性能更高,但不支持排序和范围查询。

在面试中,理解两者的区别并能够根据场景选择合适的容器是非常重要的。

THE END
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容