C++STL中unique函数详解(源码之前——了无秘密)

源码之前——了无秘密。

C++STL中unique函数详解(源码之前——了无秘密)

  • 总结

    unique函数是属于STL中比较常用的函数,因为我们如果用的存储结构不是set容器,或者说我们想主动进行元素去重,那么unique函数就可以帮到我们,它的作用自然就是元素去重,即“删除”序列中的所有相邻的重复元素(只保留一个)。注意我们这里的“删除”并不是真的删除,只是用不重复元素顶替重复元素,假设有一个已经排好序了的 n n 个元素的容器,现其中有 k k 个不重复元素,那么经过unique函数处理后前k个元素是不重复的元素,后面的 ( n k ) (n-k) 个元素与原来的容器中是相同的,我们只对前面进行了操作,也就是说前面的重复元素都被后面的不重复元素顶替了。这一定要理解。由于它“删除”的相邻的重复元素,所以我们在使用unique函数之前,一定要先排好序。

  • 函数原型

    iterator unique(iterator it_1,iterator it_2,bool MyFunc);
    

    参数列表中前两个参数都是迭代器,表示对区间[it_1,it_2)内进行去重。(区间为左闭右开,很多STL函数都是这样)。那最后一个是什么呢?就是我们自定义的元素是否相等函数对象。那什么时候需要定义呢?就是你想认为元素之间应该怎样才算相等的时候定义。不一定要i==j,我也可以定义相等的含义为i+1==j,这是都可以的。返回值是指向最后一个元素的下一个元素的迭代器

  • 理解本质

    我们来看unique函数的定义,仔细理解它为什么能实现这样的功能,这是关键。

  template <class ForwardIterator>
  ForwardIterator unique (ForwardIterator first, ForwardIterator last)
  {
    //这里隐藏了第三个参数,则使用系统默认的相等机制。
    if (first==last) return last;//判断是否相等,若相等,则表示数组为空。
  
    ForwardIterator result = first;//利用result迭代器去实现功能。
    while (++first != last)//开始遍历区间[first,last)
    {
        //注意first和result,它们都在变,形成一个同步的取缔,其中first一直往后寻找不重复的元素,而result停留在重复的元素等待取缔。仔细理解下面这个if语句。退出循环时也就遍历完成,此时result指向的是最后一个不重复元素。
      if (!(*result == *first))  // or: if (!pred(*result,*first)) for version (2)
        *(++result)=*first;
    }
    return ++result;//这里++,我们返回的就是最后一个不重复元素的下一个迭代器。
  }

通过理解完函数定义,我想我们对unique函数的功能和作用摸得也足够清了吧。

  • 配合erase函数真正删除元素

    我们在前面特别强调过unique函数并不会真正删除元素,而是用替代的方法来实现。容器的大小是不会变得,那么我们如果想真正删除元素我们该怎么办呢?我们想想,unique函数的返回值是指向最后一个不相等的元素的下一个元素的迭代器,我们只要接收这个返回值,利用erase函数把后面元素都给直接删除即可。

  • 函数用法实例

    测试代码:

  /*
  *邮箱:[email protected]
  *blog:https://me.csdn.net/hzf0701
  *注:文章若有任何问题请私信我或评论区留言,谢谢支持。
  *
  */
  #include<bits/stdc++.h>	//POJ不支持
  
  #define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
  #define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
  #define pb push_back
  #define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
  #define fi first
  #define se second
  #define mp make_pair
  
  using namespace std;
  
  const int inf = 0x3f3f3f3f;//无穷大
  const int maxn = 1e5;//最大值。
  typedef long long ll;
  typedef long double ld;
  typedef pair<ll, ll>  pll;
  typedef pair<int, int> pii;
  //*******************************分割线,以上为自定义代码模板***************************************//
  
  bool MyFunc(int i,int j){
  	return i+1==j;//我们这里自定义相等规则为i+1==j。
  }
  int main(){
  	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
  	IOS;
  	int nums[]={1,1,2,3,3,4,5,7,8,7,8,9,9};//这里我已经排好序了,如果没有排好序一定要排序。
  	int len=sizeof(nums)/4;
  	vector<int> temp1(nums,nums+len);
  	vector<int> temp2(temp1);
  	cout<<"去重前容器中的元素"<<endl;
  	rep(i,0,len-1){
  		cout<<temp1[i]<<" ";
  	}
  	cout<<endl;
  	unique(temp1.begin(),temp1.end());
  	unique(temp2.begin(),temp2.end(),MyFunc);
  	cout<<"使用两个参数(默认相等规则)的unique去重后的容器元素。"<<endl;
  	rep(i,0,len-1){
  		cout<<temp1[i]<<" ";
  	}
  	cout<<endl;
  	cout<<"使用三个参数(自定义相等规则)的unique去重后的容器元素。"<<endl;
  	rep(i,0,len-1){
  		cout<<temp2[i]<<" ";
  	}
  	return 0;
  }

测试结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/hzf0701/article/details/107890201
今日推荐