- C++
unique到底是干嘛的
- 2025-2-23 19:44:17 @
在 C++ STL 中,std::unique
是一个用于移除相邻重复元素的算法。它不会直接删除容器中的元素,而是通过覆盖重复元素的方式将不重复的元素移动到容器前部,并返回新的逻辑结尾的迭代器。以下是它的核心用法和注意事项:
函数原型
template< class ForwardIt >
ForwardIt unique( ForwardIt first, ForwardIt last );
template< class ForwardIt, class BinaryPredicate >
ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p );
- 参数:
first, last
:需要处理的元素范围(前闭后开区间)。p
:自定义的二元谓词(判断两个元素是否“相等”)。
- 返回值:指向处理后范围新结尾的迭代器。
核心行为
- 移除相邻重复:仅处理相邻的重复元素。
- 不改变容器大小:返回的新迭代器标记新结尾,但容器物理大小不变。
- 需要配合
erase
:通常与容器的erase
方法结合使用以实际删除元素。
基本用法示例
示例 1:去除非相邻重复(需先排序)
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 2, 3, 2, 4, 4, 5};
// 1. 先排序(去除非相邻重复)
std::sort(vec.begin(), vec.end());
// 2. 移除相邻重复元素
auto new_end = std::unique(vec.begin(), vec.end());
// 3. 实际删除尾部多余元素
vec.erase(new_end, vec.end());
// 输出结果:1 2 3 4 5
for (int num : vec) std::cout << num << " ";
}
示例 2:自定义去重条件
struct Person {
std::string name;
int age;
};
int main() {
std::vector<Person> people = {
{"Alice", 25}, {"Bob", 30}, {"Alice", 25}, {"Charlie", 35}
};
// 自定义谓词:按 name 去重
auto new_end = std::unique(people.begin(), people.end(),
[](const Person& a, const Person& b) {
return a.name == b.name;
});
people.erase(new_end, people.end());
// 结果保留第一个 Alice、Bob、Charlie
}
注意事项
场景 | 处理方式 |
---|---|
非排序容器去重 | 先调用 std::sort ,否则只能去除相邻重复 |
保留最后一个重复项 | 结合 std::reverse 反向处理(见下方代码) |
自定义类型去重 | 必须提供正确的谓词(如比较结构体的某个字段) |
字符串去重 | 直接应用即可(例如去除连续重复字符) |
保留最后一个重复项(反向去重)
std::vector<int> vec = {1, 2, 2, 3, 2, 4, 4, 5};
std::sort(vec.begin(), vec.end()); // 排序
std::reverse(vec.begin(), vec.end()); // 反转
auto new_end = std::unique(vec.begin(), vec.end());
vec.erase(new_end, vec.end());
std::reverse(vec.begin(), vec.end()); // 反转回来
// 结果:1, 2, 3, 4, 5 → 若原数据未排序可能保留不同元素
性能分析
- 时间复杂度:(O(n)),遍历一次容器。
- 适用场景:
- 需要保留唯一元素但顺序敏感(如日志去重)。
- 配合排序实现全局去重(时间复杂度 (O(n \log n)))。
总结
std::unique
的正确使用流程:
- 排序(若需全局去重)。
- 调用
std::unique
获取新结尾。 - 使用
erase
删除尾部冗余元素。
0 条评论
目前还没有评论...