前面一节我们学习了复制算法 reverse_copy() 函数,读者是否还记得它的功能是什么吗?没错,该函数能够将序列元素反转顺序后复制到目标区域。本节我们将学习一个新的算法,移除算法,顾名思义,该算法的功能是移除序列中不符合条件的元素,注意是移除而不是删除,实际上是覆盖。unique() 函数就是一个移除算法,"unique" 意为"唯一的",但读者千万别认为使用这个函数就能实现真的”独一无二“,每个元素都是唯一存在,注意这个函数只能去除邻近的重复元素,想要完全去重需要配合sort()函数和erase()成员函数。

unique() 函数的语法格式如下:

template< class ForwardIt >
ForwardIt unique( ForwardIt first, ForwardIt last );
template< class ForwardIt, class BinaryPredicate >
ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p );

unique(first, last) 函数的功能是:移除区间 [first, last) 中相邻的重复元素,只保留每个重复组的第一个元素。该函数返回指向去重后新逻辑末尾的迭代器。注意,unique 并不会真正删除元素,而是通过覆盖的方式重排序列,将不重复的元素移到前面。比如我们有一个序列:{1, 2, 2, 3, 2, 4, 4, 5},使用 unique 处理后变为 {1, 2, 3, 2, 4, 5, x, x},其中 'x' 表示被覆盖的原始值,函数返回指向第6个位置的迭代器。

下面我们通过代码来演示 unique() 函数的实际应用:

#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>//移动迭代器 
#include<string>
using namespace std;
void test() {
     
   vector<char> v{'d','o','t','c','p','p','.','c','o','m'}; 
   /*去重前*/ 
   cout << "未去重之前:\t";
     for_each(v.begin(), v.end(), [](const char&c){
        cout << c;
    });
    cout << '\n';
    /*开始去重*/
	unique(v.begin(),v.end());
	/*去重后*/ 
   cout << "去重之后:\t";
    for_each(v.begin(), v.end(), [](const char&c){
        cout << c;
    });
    cout << '\n';
    /*开始去重*/
} 
int main(){
    system("title dotcpp.com");
    test();
    return 0;
}

编译结果如下:

unique()函数

观察输出我们发现,前面重复的元素被后面的元素覆盖了,多余的"pp"变成"p","com"变成"comm",本质上是覆盖行为,如果想要删除元素需要配合容器自带的成员函数erase()函数进行,像这样:

v.erase(unique(v.begin(),v.end()),v.end());//unique()函数配合erase()成员函数实现去重操作

总结:unique() 函数提供了一个高效的相邻重复元素移除机制,它通常需要与 erase() 成员函数配合使用来真正缩小容器,与 sort() 函数配合使用来实现完全去重;同时在蓝桥杯、ACM等算法竞赛上,unique() 是数据清洗、统计分析等问题的必备工具,是 STL 算法库中一个实用且高效的函数。

点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)