map、set、multimap、multiset有什么区别?

参考回答

mapsetmultimapmultiset 是 C++ STL 中的关联容器,底层均基于 红黑树 实现。它们的主要区别在于是否存储键值对、是否允许键重复、以及操作方式的差异。

主要区别:

  1. 键值对存储
    • mapmultimap 存储键值对 (key-value)。
    • setmultiset 只存储键 (key)。
  2. 键的唯一性
    • mapset 中的键是唯一的。
    • multimapmultiset 允许键重复。
  3. 常见操作
    • mapset 适合需要快速查找唯一键的场景。
    • multimapmultiset 适合需要存储重复键的场景。

详细讲解与拓展

1. map

  • 特点
    • 存储唯一的键值对 (key-value)。
    • 自动按照键排序(默认升序)。
    • 可以通过键快速查找对应的值。
  • 示例

#include <map>
#include <iostream>
using namespace std;

int main() {
    map<int, string> myMap;
    myMap[1] = "One";
    myMap[2] = "Two";
    myMap[1] = "New One";  // 键 1 的值被更新

    for (const auto& [key, value] : myMap) {
        cout << key << ": " << value << endl;
    }

    return 0;
}

输出:

1: New One
2: Two
  • 适用场景
    适用于需要快速查找唯一键和值的场景,例如存储配置项、字典等。

2. set

  • 特点
    • 只存储唯一的键 (key)。
    • 自动按照键排序(默认升序)。
    • 不支持重复键的插入。
  • 示例

#include <set>
#include <iostream>
using namespace std;

int main() {
    set<int> mySet = {10, 20, 30};
    mySet.insert(20);  // 插入失败,键已存在
    mySet.insert(40);  // 插入成功

    for (int val : mySet) {
        cout << val << " ";
    }

    return 0;
}

输出:

10 20 30 40
  • 适用场景
    适用于需要快速查找唯一元素的场景,例如集合操作、不重复的记录存储等。

3. multimap

  • 特点
    • 存储键值对 (key-value)。
    • 允许键重复,多个相同的键可以有不同的值。
    • 自动按照键排序(默认升序)。
  • 示例

#include <map>
#include <iostream>
using namespace std;

int main() {
    multimap<int, string> myMultimap;
    myMultimap.insert({1, "One"});
    myMultimap.insert({2, "Two"});
    myMultimap.insert({1, "Another One"});  // 键 1 可以重复

    for (const auto& [key, value] : myMultimap) {
        cout << key << ": " << value << endl;
    }

    return 0;
}

输出:

1: One
1: Another One
2: Two
  • 适用场景
    适用于需要存储重复键的场景,例如分类存储数据、映射多个值到同一键等。

4. multiset

  • 特点
    • 只存储键 (key)。
    • 允许键重复,且自动按照键排序(默认升序)。
    • 常用于统计或存储重复数据。
  • 示例

#include <set>
#include <iostream>
using namespace std;

int main() {
    multiset<int> myMultiset = {10, 20, 10};
    myMultiset.insert(10);  // 键 10 可以重复

    for (int val : myMultiset) {
        cout << val << " ";
    }

    return 0;
}

输出:

10 10 10 20
  • 适用场景
    适用于需要存储重复元素的场景,例如统计频率、处理多重集合等。

5. 功能对比总结

容器 是否存储键值对 是否允许键重复 自动排序 查找时间复杂度 典型操作
map 是(key-value 是(升序) (O(\log n)) 单键查找、更新
set 否(key 是(升序) (O(\log n)) 唯一集合
multimap 是(key-value 是(升序) (O(\log n)) 重复键分组存储
multiset 否(key 是(升序) (O(\log n)) 重复元素统计

6. 应用场景总结

  • map
    • 存储唯一键值对,例如配置项或字典。
    • 快速查找键对应的值。
  • set
    • 唯一元素集合,例如防止重复数据或快速判断某个值是否存在。
  • multimap
    • 允许多个值对应同一键,例如按类别分组存储。
  • multiset
    • 统计元素出现次数,例如频率统计、多重集合的处理。

总结

mapsetmultimapmultiset 的主要区别在于是否存储键值对、是否允许键重复以及应用场景不同。理解它们的底层实现(红黑树)和特性,可以在实际开发中根据需求选择合适的容器。如果不需要排序且追求更高性能,可以考虑它们的无序版本(如 unordered_mapunordered_set)。

发表评论

后才能评论