std::set自动去重并按升序排序,底层基于红黑树实现;插入重复元素被忽略,返回值.second指示是否成功插入;降序需传std::greater{};自定义类型须提供operator
set 本身就会自动去重和排序,不需要额外操作
你往 std::set 里插重复元素,它直接无视——不是报错,也不是覆盖,是“不存”。底层用红黑树实现,插入时就按 operator(或自定义比较器)排序,所以遍历出来天然升序、无重复。
常见错误现象:set.insert(x) 返回一个 std::pair<iterator bool></iterator>,很多人只取迭代器,却忽略 second 字段才是“是否真插入了”的判断依据。误以为插完就一定有新元素,结果逻辑出错。
- 如果需要知道某次插入是否成功,必须检查返回值的
.second - 想按降序排列?传
std::greater<int>{}</int>作模板参数:std::set<int std::greater>></int> - 自定义类型必须提供可比较的
operator,或显式传比较函数对象;否则编译失败,错误信息类似:<code>invalid operands to binary expression ('const MyType' and 'const MyType')
别用 set 去处理已有重复数据再“去重”
有人把一堆重复数字先塞进 vector,再一个个 insert 到 set 里,以为这是“去重手段”。这可行但低效:每次 insert 是 O(log n),总时间 O(m log n)(m 是原始元素数,n 是去重后大小),远不如先 sort + unique —— 后者是 O(m log m) 排序 + O(m) 扫描,对大数组更友好。
- 场景明确是“一次性清洗已有容器”,优先考虑
std::sort+std::unique+erase -
set的优势在动态增删+实时有序,比如维护一个不断变化的排行榜、查找中位数、区间查询等 - 内存开销更大:每个节点要存左右子节点指针+颜色位,比
vector或unordered_set占更多空间
想保留插入顺序又去重?set 不行,换 unordered_set 或 vector + find
std::set 天然破坏插入顺序——它只认大小关系。如果你需要“第一次出现的元素排前面,后续重复跳过”,set 无法满足。