*C++ 集合(`set`、`unordered_set`、`map`、`unordered_map`)全面解析

🚀 C++ 集合(setunordered_setmapunordered_map)全面解析

C++ STL 提供了多种高效存储和查找数据的容器,本文深入解析集合(Set)和映射(Map)及其变体的特性、用法和适用场景。


📌 1. setunordered_set(集合)

1.1 set(有序集合)

  • 特点

    • 自动排序(默认升序)。
    • 元素唯一,不允许重复
    • 底层数据结构:红黑树
    • 查找、插入、删除的时间复杂度:O(log n)
    • 元素不可修改(修改会破坏排序)。
  • 头文件#include <set>

  • 示例代码

#include <set>
using namespace std;

int main() {
    set<int> s;
    s.insert(5);
    s.insert(3);
    s.insert(8);
    s.insert(3);  // 重复元素插入失败

    // 遍历输出:3 5 8(自动排序)
    for (int x : s) cout << x << " ";

    // 查找元素
    if (s.find(5) != s.end()) {
        cout << "\n5 存在" << endl;
    }

    s.erase(5);  // 删除元素
    return 0;
}

🌟 适用场景:需有序且元素唯一的场景(如去重+排序)。


1.2 unordered_set(无序集合)

  • 特点

    • 元素唯一,无序存储
    • 底层数据结构:哈希表
    • 查找、插入、删除的平均时间复杂度:O(1),最坏情况 O(n)。
    • 需自定义哈希函数(若键为自定义类型)。
  • 头文件#include <unordered_set>

  • 示例代码

#include <unordered_set>
using namespace std;

int main() {
    unordered_set<int> us;
    us.insert(5);
    us.insert(3);
    us.insert(8);
    us.insert(3);  // 插入失败

    // 遍历输出顺序不定(如5 3 8)
    for (int x : us) cout << x << " ";
    return 0;
}

🌟 适用场景:需快速查找且不关心顺序。


📌 2. mapunordered_map(键值对映射)

2.1 map(有序映射)

  • 特点

    • 按键自动排序(默认升序)
    • 键唯一,值可重复
    • 底层数据结构:红黑树
    • 操作时间复杂度:O(log n)
    • 键不可修改,值可修改。
  • 头文件#include <map>

  • 示例代码

#include <map>
using namespace std;

int main() {
    map<string, int> m;
    m["apple"] = 3;   // 插入或修改键为"apple"的值
    m.insert({"banana", 2});  // 插入键值对,若键存在则失败

    // 遍历按键升序输出
    for (auto& p : m) {
        cout << p.first << ": " << p.second << endl;
    }
    return 0;
}

🌟 适用场景:需有序键值对的存储(如字典排序)。


2.2 unordered_map(无序映射)

  • 特点

    • 无序存储键值对
    • 底层数据结构:哈希表
    • 平均时间复杂度:O(1),最坏情况 O(n)。
    • 需为自定义键类型提供哈希函数和 == 运算符。
  • 头文件#include <unordered_map>

  • 示例代码

#include <unordered_map>
using namespace std;

int main() {
    unordered_map<string, int> um;
    um["apple"] = 3;
    um["banana"] = 2;
    
    // 遍历输出顺序不定
    for (auto& p : um) {
        cout << p.first << ": " << p.second << endl;
    }
    return 0;
}

🌟 适用场景:需快速查找键值对且不关心顺序。


📌 3. 允许多个相同元素的集合(Multi 版本)

3.1 multiset(有序多重集合)

  • 特点

    • 允许重复元素,自动排序。
    • 底层结构:红黑树。
    • 时间复杂度:O(log n)。
  • 头文件#include <set>

  • 示例代码

multiset<int> ms;
ms.insert(3);
ms.insert(3);  // 允许重复
// 输出:3 3 5 8(有序)

3.2 multimap(有序多重映射)

  • 特点

    • 允许重复键,按键排序。
    • 不支持 operator[](因键不唯一)。
  • 头文件#include <map>

  • 示例代码

multimap<string, int> mm;
mm.insert({"apple", 3});
mm.insert({"apple", 4});  // 允许重复键

3.3 unordered_multisetunordered_multimap

  • 特点
    • 无序存储,允许重复元素/键。
    • 底层结构:哈希表。
    • 平均时间复杂度:O(1)。

📊 总结对比表

容器有序性唯一性底层结构时间复杂度适用场景
set✅ 升序键唯一红黑树O(log n)有序唯一集合
unordered_set❌ 无序键唯一哈希表O(1) 平均, O(n) 最坏快速查找无需排序
map✅ 升序键唯一红黑树O(log n)有序键值对
unordered_map❌ 无序键唯一哈希表O(1) 平均, O(n) 最坏快速键值查找
multiset✅ 升序允许重复红黑树O(log n)有序可重复集合
multimap✅ 升序允许重复键红黑树O(log n)有序键可重复映射
unordered_multiset❌ 无序允许重复哈希表O(1) 平均, O(n) 最坏快速查找可重复元素
unordered_multimap❌ 无序允许重复键哈希表O(1) 平均, O(n) 最坏快速查找可重复键

🎯 选择指南

  • 快速查找 + 无需排序unordered_map / unordered_set
  • 有序存储map / set
  • 允许重复元素multiset / multimap
  • 自定义键类型 → 提供哈希函数和 == 运算符(仅 unordered 容器需要)

⚠️ 注意事项

  1. 哈希冲突unordered_* 容器在哈希冲突严重时性能下降,需合理设计哈希函数。
  2. 修改元素setmap 的键不可修改,值可修改(map 的值通过迭代器修改)。
  3. 插入方式mapoperator[] 会插入默认值,而 insert 不会覆盖已有键。
  4. 自定义键:使用 unordered_map 自定义键时,需特化 std::hash 并重载 operator==

通过理解各容器的特性,能更高效地选择适合的数据结构解决问题。 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值