0

0

C++ set怎么去重 C++集合容器自动排序去重原理【数据结构】

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-31 09:39:09

|

184人浏览过

|

来源于php中文网

原创

set插入自动去重依赖红黑树的二分查找与等价判断(非相等),要求比较函数满足严格弱序;若自定义类型仅重载operator==而未提供operator

c++ set怎么去重 c++集合容器自动排序去重原理【数据结构】

set 插入时自动去重靠的是 std::less 和等价判断

不是靠“查重后再插入”,而是靠红黑树的插入逻辑:每次插入先按排序规则(默认 std::less)做二分查找,若已存在「等价」元素(即既不小于也不大于),就直接丢弃。这里的关键是「等价」≠「相等」——对 int区别,但自定义类型若只重载了 operator== 却没适配比较函数,set 仍会插入“看似重复”的元素。

常见错误现象:set 插入两个字段完全相同的对象,结果 size 变成 2。原因往往是只写了 operator==,却没提供 operator 或自定义 Compare 函数对象。

  • 必须确保比较函数满足严格弱序(strict weak ordering):反身性、反对称性、传递性、不可比性的传递性
  • 不要用 return a.x == b.x && a.y == b.yoperator —— 这不满足严格弱序
  • 推荐写法:return std::tie(a.x, a.y)

为什么 set 不用哈希而用红黑树实现

因为 set 的核心契约是「有序 + 去重」,不是「快查」。红黑树天然支持 O(log n) 插入/删除/查找,且中序遍历即升序;而哈希表(如 unordered_set)虽平均 O(1),但不保证顺序,也无法直接支持 lower_boundupper_bound 等范围操作。

性能影响明显:如果你只需要去重、不关心顺序,unordered_set 更快;但一旦需要迭代有序、或频繁调用 lower_bound 查找前驱后继,set 是唯一合理选择。

立即学习C++免费学习笔记(深入)”;

怪兽AI数字人
怪兽AI数字人

数字人短视频创作,数字人直播,实时驱动数字人

下载
  • set 迭代器是双向迭代器,可 ++/--;unordered_set 是前向迭代器,只能 ++
  • set::find 返回指向有序位置的迭代器;unordered_set::find 返回任意位置的迭代器
  • 内存占用:红黑树每个节点带颜色和指针,比哈希桶略高,但更稳定(无哈希冲突扩容抖动)

手动触发去重?没必要,但要注意 insert 返回值

set::insert 返回 std::pair,其中 bool 表示是否成功插入(true = 新元素,false = 已存在)。这不是“手动去重”,而是标准协议的一部分,用于判断是否发生实际变更。

容易踩的坑:有人误用 set::emplace_hint 并传错 hint,导致性能退化甚至逻辑错误;还有人把 set 当作临时去重容器,反复构造再清空,其实不如直接用 std::vector + std::sort + std::unique(尤其数据量小或只去重一次时)。

  • 大批量插入建议用范围构造:set s(v.begin(), v.end());,比循环 insert 快(内部优化为批量建树)
  • 若只是临时去重并转回 vector,且不需要中间有序,unordered_set + vector 构造更快
  • 别对 set 调用 std::unique —— 它要求相邻重复,而 set 根本不会存重复

自定义类型去重失败的典型调试路径

set 明明该去重却没去,优先检查三件事:

  • 确认 MyClass 的比较函数是否被正确使用:在 set 模板参数里显式传入,或确保 operator 是 public 且非模板
  • 打印插入前后 s.size() 和遍历输出,验证是否真没去重,还是你误判了“相同”逻辑(比如浮点数直接比较)
  • std::is_sorted(s.begin(), s.end(), comp) 检查是否真有序——如果返回 false,说明比较函数违反严格弱序,这是根本原因

最隐蔽的问题:比较函数里用了未初始化成员、或依赖外部状态(如全局变量),导致行为不稳定。这种 bug 往往只在特定编译器或优化等级下暴露。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Sass和less的区别
Sass和less的区别

Sass和less的区别有语法差异、变量和混合器的定义方式、导入方式、运算符的支持、扩展性等。本专题为大家提供Sass和less相关的文章、下载、课程内容,供大家免费下载体验。

204

2023.10.12

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

395

2023.09.04

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

82

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

82

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

503

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

545

2024.08.29

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号