选 std::set 还是 std::unordered_set,核心看是否需要有序、是否容忍最坏 O(n) 性能、以及数据量与哈希质量;需自动排序、范围查询或稳定遍历选 set;重平均性能、无序存在性检查且哈希合理选 unordered_set。
选 std::set 还是 std::unordered_set,核心看你要不要有序、是否在意最坏性能、以及数据量和哈希质量如何。
std::set 基于红黑树实现,插入、查找、删除都是 O(log n),且元素始终按严格弱序(默认升序)排列。如果你依赖遍历顺序(比如取最小/最大值、范围查询 lower_bound / upper_bound、或需迭代器稳定前进),它不可替代。
begin() 到 end() 正序遍历,天然有序equal_range 找等价区间,适合有重复逻辑的扩展(虽然 set 本身不存重复)std::unordered_set 是哈希表,平均时间复杂度为 O(1),但最坏可能退化到 O(n)(大量哈希冲突时)。它不保证顺序,遍历时是“乱序”的(取决于桶分布和插入历史)。
count / find)、去重插入,且不关心顺序set 高 2–5 倍(尤其 n > 1000 时),但前提是哈希函数合理、负载因子不过高re
serve(n) 预分配桶数,减少 rehash;用 max_load_factor(0.75) 控制密度,防退化当元素极少时,红黑树的常数开销和哈希表的指针跳转、桶管理成本接近,实测性能可能互有胜负。此时可按语义选:
— 要顺序 → set
— 图省事、key 是 int/string → unordered_set(标准库对它们有优化哈希)
unordered_set 的默认哈希通常很高效set 只需提供 operator;unordered_set 还得写哈希函数 + operator==,成本更高
std::set 每个节点至少含 3 指针(左右子+父)+ key,内存占用较紧凑;unordered_set 有桶数组 + 链表/开放寻址结构,空载时也占较多内存,且 rehash 会临时翻倍。
unordered_set 迭代器在 insert/rehash 时可能全部失效(而 set 只有删掉的那个失效)set 的顺序一致性更易推理set 的树结构可逐步跟踪;unordered_set 内部状态难直观观察