map和set

1.核心总览

set:有序、唯一的集合,只存单个值(key = value)
map:有序、唯一的键值对,存 key + value(key 唯一,value 可重复)

相同点(底层 + 特性)
底层:红黑树(平衡二叉搜索树)
特性:key 自动升序排序、key 不可重复
效率:查找 / 插入 / 删除 → 稳定 O(log n)
限制:不能修改 key(修改会破坏红黑树结构)

核心区别表格:

特性 set map
存储数据 单个值(key) 键值对(key: value)
key 作用 既是键也是值 唯一索引
访问方式 只能用迭代器 支持 [key] 下标访问
元素类型 T pair<const K, V>
重复元素 不允许 不允许重复 key

2.使用示例

set 使用示例:

cpp 复制代码
void test_set() {
    // 1. 定义:set<类型>
    set<int> s;

    // 2. 插入(自动去重+排序)
    s.insert(3);
    s.insert(1);
    s.insert(2);
    s.insert(3); // 重复,自动忽略

    // 3. 遍历(迭代器,有序输出:1 2 3)
    for (auto it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }

    // 4. 查找
    auto it = s.find(2);
    if (it != s.end()) cout << "\n找到元素:" << *it;

    // 5. 删除
    s.erase(3);
}

map 使用示例:

cpp 复制代码
void test_map() {
    // 1. 定义:map<key类型, value类型>
    map<int, string> m;

    // 2. 插入(key唯一,自动按key排序)
    m.insert(make_pair(3, "张三"));
    m[1] = "李四";   // 最常用:[] 插入/修改
    m[2] = "王五";
    m[3] = "张三丰"; // key重复,覆盖value

    // 3. 遍历(有序输出:1 2 3)
    for (auto& p : m) {
        cout << p.first << ":" << p.second << " ";
    }

    // 4. 查找
    auto it = m.find(2);
    if (it != m.end()) cout << "\n找到:" << it->second;

    // 5. 删除
    m.erase(3);
}

当然头文件也是必须的:

cpp 复制代码
#include <iostream>
#include <set>    // set
#include <map>    // map
using namespace std;

3.map的元素

std::map 容器内部存储的每一个元素,都必须是 std::pair<const Key, T> 类型 **,这是 C++ 标准规定的,没有例外!

map 的全称是键值对映射容器,它必须存储 key(键

) + value(值) 两部分。

C++ 用 std::pair 这个结构体来绑定这两部分:

cpp 复制代码
// map 内部固定的元素类型(背下来)
using value_type = pair<const Key, T>;

pair.first → key(带 const,不能修改!)
pair.second → value(可以修改)

3 种插入方式,本质全是 pair:

cpp 复制代码
map<int, string> m;

// 方式1:[] 运算符(最常用)→ 底层自动生成 pair
m[1] = "张三";   

// 方式2:花括号初始化 → C++11 隐式转 pair
m.insert({2, "李四"});  

// 方式3:显式写 pair → 最原始的写法
m.insert(pair<int, string>(3, "王五"));

不管怎么写,存进 map 里的都是 pair<const int, string>

遍历 map 时,必须用 pair 接收:

cpp 复制代码
// 遍历 map,迭代器指向的就是 pair!
for (auto& element : m) {
    // element 的类型就是 pair<const int, string>
    cout << element.first << " : " << element.second << endl;
}

如果元素不是 pair,你根本无法用 .first / .second 访问!

① 为什么是 const Key?

map 底层是红黑树,key 用来排序,一旦插入就不能改,否则会破坏树结构。

所以 pair 的第一个成员强制 const,禁止修改 key。

② 可以存自定义类型吗?

可以!但依然要包装成 pair:

cpp 复制代码
// 自定义结构体
struct Student { int id; string name; };

// map 元素依然是 pair:key是int,value是自定义结构体
map<int, Student> m;
m[101] = {101, "小明"}; 

4.核心区别

容器 存储元素 结构 有无 .first/.second
map pair<const K, V> 键 + 值 ✅ 有
set const T 单个值 ❌ 无

5.运用场景

1.std::set 适用场景

核心:只需要存【单个值】、要求【自动去重】、【有序】、高频判断【是否存在】

关键词:去重、存在性检查、有序集合、无映射关系。

1. 黑名单 / 白名单

场景:判断用户、IP、设备是否在禁止列表里

cpp 复制代码
set<string> black_list;
black_list.insert("192.168.1.1");

// 核心需求:查 有没有!
if(black_list.count("192.168.1.1")) {
    cout << "禁止访问";
}

只用存一个 IP,不需要对应其他数据 → set 完美

2.数据自动去重 + 排序

场景:收集学生学号、订单号,要求不重复、自动排好序

cpp 复制代码
set<int> ids;
ids.insert(1001);
ids.insert(1003);
ids.insert(1001); // 重复,自动忽略
3.有序唯一集合

场景:排行榜、分类标签、单词去重统计

2.std::map 适用场景

核心:需要存【键值对】、通过 key 快速找 value、key 有序、一一映射

关键词:映射关系、查值、ID→信息、配置表

1. 唯一标识 → 详细信息

场景:用户 ID 查用户信息、学号查学生、工号查员工

cpp 复制代码
map<int, Student> student_map;
student_map[1001] = {"张三", 18, "计算机"};

// 核心需求:用学号找学生详情
auto stu = student_map[1001]; 

必须存 key + value → 只能用 map

2. 统计计数

场景:统计单词出现次数、商品销量、点击量

cpp 复制代码
map<string, int> count_map;
count_map["hello"]++;  // 单词 hello 计数+1
3. 有序配置 / 字典

场景:配置文件(key = 配置名,value = 值)、有序字典

极简对比表:

需求 选择 例子
存 IP 黑名单 set 只存 IP,查是否存在
学号→学生信息 map 一个学号对应一个学生对象
单词去重 set 只保留唯一单词
单词出现次数 map 单词 → 次数
有序编号 set 自动排序不重复
用户 ID→昵称 map 一一映射

谢谢

相关推荐
basketball6161 小时前
C++进阶:3. unique_ptr 现代C++内存管理的基石
java·jvm·c++
FFZero11 小时前
[mpv脚本系统] (三) C 函数如何注册成 Lua 模块
c++·音视频·lua
我不是懒洋洋1 小时前
从零实现一个Redis客户端:RESP协议与网络编程
开发语言·c++
玖玥拾1 小时前
C/C++ 基础笔记(六)
c语言·c++·内存管理
秋田君1 小时前
2026 前端新出路:掌握 C++ 核心语法,无缝衔接 QT 桌面开发
前端·c++·qt
handler011 小时前
【C++11 】Lambda 表达式、std::function 与 std::bind 解析
c++·c·c++11·bind·解耦·function·lamda
字节高级特工2 小时前
C++11(二) 革新:引用折叠与lambda表达式
java·开发语言·c++·算法
白驹笙鸣2 小时前
STL allocator作用
开发语言·c++
小小编程路2 小时前
C++ STL 原理与性能
开发语言·c++