std::unique只能移除相邻重复元素,因此未排序vector调用后无效;必须先sort使相同元素相邻,再unique标记重复,最后erase真正删除。

为什么 std::unique 不能直接对未排序的 vector 去重
std::unique 只移除「相邻重复元素」,不是全局去重。如果 vector 是 {1,3,2,3,1},调用 unique 后仍是原样——因为所有重复值都不相邻。
它真正起作用的前提是:相同元素必须连续出现。所以必须先 sort,再 unique,否则结果不可靠。
sort + unique + erase 三步完整写法(C++11 及以后)
这是最常用、最稳妥的去重组合。注意三步缺一不可:sort 排序 → unique 标记重复 → erase 真实删除。
std::vectorv = {3, 1, 4, 1, 5, 9, 2, 6, 5}; std::sort(v.begin(), v.end()); // 排序:{1,1,2,3,4,5,5,6,9} auto last = std::unique(v.begin(), v.end()); // 返回新逻辑尾迭代器 v.erase(last, v.end()); // 真删掉重复部分
常见错误:
• 忘了 v.erase,只调 unique —— 容器大小不变,只是把重复元素挪到末尾;
• 用 v.end() - 1 或硬算长度来删 —— 错误,必须用 unique 返回的迭代器;
• 对 vector<:string> 等类型没写自定义比较函数,但其实默认比较已够用,除非要忽略大小写等特殊逻辑。
去重后保持原始顺序?sort 就不适用了
如果输入是 {3,1,4,1,5,9,2,6,5},你希望输出是 {3,1,4,5,9,2,6}(首次出现顺序保留),那 sort+unique 会破坏顺序,完全不合适。
此时该用 std::unordered_set 辅助遍历:
立即学习“C++免费学习笔记(深入)”;
std::vectorv = {3,1,4,1,5,9,2,6,5}; std::unordered_set seen; std::vector result; for (int x : v) { if (seen.insert(x).second) { // insert 返回 pair ,second 为 true 表示新插入 result.push_back(x); } } // result = {3,1,4,5,9,2,6}
要点:
• unordered_set 插入平均 O(1),整体 O(n),比排序 O(n log n) 更快(尤其大数据量);
• 如果元素不可哈希(比如自定义类),得改用 std::set(O(log n) 插入,总 O(n log n));
• 不要边遍历边 erase 原 vector,容易迭代器失效。
自定义类型的 unique 去重要注意什么
比如 struct Point { int x, y; };,直接用 sort + unique 会编译失败,因为缺少比较和相等操作符。
必须提供:
• operator(供 sort 使用)
• operator==(供 unique 使用,或显式传 binary_pred)
struct Point {
int x, y;
bool operator<(const Point& other) const { return x != other.x ? x < other.x : y < other.y; }
bool operator==(const Point& other) const { return x == other.x && y == other.y; }
};
std::vector pts = {{1,2}, {3,4}, {1,2}};
std::sort(pts.begin(), pts.end());
pts.erase(std::unique(pts.begin(), pts.end()), pts.end());
容易被忽略的点:
• operator 必须是严格弱序(比如不能只比 x,否则 {1,2} 和 {1,3} 会判为相等);
• 如果不想改结构体,也可以在 sort 和 unique 中分别传 lambda,但需保证两者逻辑一致;
• unique 的谓词(如 [](const auto&a, const auto&b){...})只用于判断「是否相邻重复」,不影响排序行为。









