std::set_union等算法要求输入序列已排序且无重复,无论容器类型;std::set_difference计算a−b而非b−a;std::set_symmetric_difference用于对称差集;unordered_set不支持这些算法,需手动实现。

用 std::set_union 求并集,但必须先排序
标准库的集合操作函数(std::set_union、std::set_difference、std::set_symmetric_difference)不关心你存的是不是数学意义上的“集合”,只认一个前提:两个输入范围必须是**已排序且无重复元素**的序列。哪怕你用 std::set 存数据,传给这些算法时也得用 begin()/end() 拿到迭代器——它们底层只是按序归并,不是靠哈希或树结构查重。
常见错误是直接对 std::vector 调用 std::set_union 却忘了排序:
std::vector<int> a = {3, 1, 4};<br>std::vector<int> b = {2, 4, 5};<br>std::vector<int> out;<br>// ❌ 错误:未排序,结果不可靠<br>std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(out));</int></int></int>
- 正确做法:先调用
std::sort,再去重(如果原始数据可能含重复) - 若原始容器已是
std::set或std::set迭代器范围,则天然有序无重,可直接用 - 输出容器需预留空间或用
std::back_inserter,否则写入越界
std::set_difference 返回 A−B,不是 B−A
这个函数名有迷惑性:它计算的是「第一个范围减第二个范围」,即 A − B,不是对称差,也不是任意方向的差。想求 B − A,得把参数顺序反过来。
示例:
std::set<int> a = {1, 2, 3, 4};<br>std::set<int> b = {3, 4, 5, 6};<br>std::vector<int> diff;<br>// ✅ 得到 {1, 2}<br>std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(diff));<br>// ✅ 想要 {5, 6},就得交换 a 和 b 的位置<br>std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::back_inserter(diff));</int></int></int>
- 别指望它自动识别容器类型——传
std::vector也行,只要已排序 - 结果中不会出现重复元素,即使输入里有重复(但前提是输入本身已去重,否则行为未定义)
- 如果 A 是空集,结果就是空;如果 B 是空集,结果等于 A
对称差集用 std::set_symmetric_difference,不是两次差集相加
虽然数学上 A ⊕ B = (A−B) ∪ (B−A),但直接调用 std::set_symmetric_difference 更安全高效。自己拼两次差集再合并,不仅多遍历、多分配内存,还容易漏掉去重逻辑(比如两次差集结果各自无重,但合起来可能有重——不过实际不会,因为 A−B 和 B−A 必然不相交;但代码可读性和维护成本上升)。
注意点:
- 输入范围仍需有序;输出也是有序的,且无重复
- 它等价于「在 A 或 B 中出现,但不同时出现在两者中」的元素
- 如果 A 和 B 完全相同,结果为空;如果完全不相交,结果就是 A 和 B 的合并
用 std::unordered_set 时没法直接用这些算法
这些 std::set_* 算法依赖随机访问迭代器和有序比较,而 std::unordered_set 只提供前向迭代器,且内部无序。想对哈希集合做并集/差集,只能手写循环或用 insert/erase 配合 find。
例如模拟 A − B:
std::unordered_set<int> a = {1, 2, 3, 4};<br>std::unordered_set<int> b = {3, 4, 5};<br>std::unordered_set<int> diff = a; // 先拷贝<br>for (int x : b) {<br> diff.erase(x); // 删除所有在 b 中存在的元素<br>}</int></int></int>
- 性能上,哈希方案平均 O(n+m),而排序+算法是 O(n log n + m log m + n + m),大数据量时哈希更优
- 但哈希不保证输出顺序;若需要有序结果,最终还得转成
std::vector再std::sort - 没有现成的对称差集成员函数,得靠两次 erase 或手动遍历判断
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











