一.unique函数
类属性算法unique的作用是从输入序列中“删除”全部相邻的反复元素。
该算法删除相邻的反复元素。然后又一次排列输入范围内的元素,而且返回一个迭代器(容器的长度没变,仅仅是元素顺序改变了),表示无反复的值范围得结束。
// sort words alphabetically so we can find the duplicates
sort(words.begin(), words.end());
/* eliminate duplicate words:
* unique reorders words so that each word appears once in the
* front portion of words and returns an iterator one past the
unique range;
* erase uses a vector operation to remove the nonunique elements
*/
vector<string>::iterator end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
在STL中unique函数是一个去重函数, unique的功能是去除相邻的反复元素(仅仅保留一个),事实上它并不真正把反复的元素删除,是把反复的元素移到后面去了。然后依旧保存到了原数组中,然后 返回去重后最后一个元素的地址,由于unique去除的是相邻的反复元素,所以一般用之前都会要排一下序。
若调用sort后。vector的对象的元素按次序排列例如以下:
sort jumps over quick red red slow the the turtle
则调用unique后,vector中存储的内容是:
注意,words的大小并没有改变,依旧保存着10个元素;仅仅是这些元素的顺序改变了。调用unique“删除”了相邻的反复值。给“删除”加上引號是由于unique实际上并没有删除不论什么元素,而是将无反复的元素拷贝到序列的前段。从而覆盖相邻的反复元素。unique返回的迭代器指向超出无反复的元素范围末端的下一个位置。
注意:算法不直接改动容器的大小。假设须要加入或删除元素。则必须使用容器操作。
example:
#include <iostream>
#include <cassert>
#include <algorithm>
#include <vector>
#include <string>
#include <iterator>
using namespace std;
int main()
{
//cout<<"Illustrating the generic unique algorithm."<<endl;
const int N=11;
int array1[N]={1,2,0,3,3,0,7,7,7,0,8};
vector<int> vector1;
for (int i=0;i<N;++i)
vector1.push_back(array1[i]);
vector<int>::iterator new_end;
new_end=unique(vector1.begin(),vector1.end()); //"删除"相邻的反复元素
assert(vector1.size()==N);
vector1.erase(new_end,vector1.end()); //删除(真正的删除)反复的元素
copy(vector1.begin(),vector1.end(),ostream_iterator<int>(cout," "));
cout<<endl;
return 0;
}
执行结果为:
二、unique_copy函数
算法标准库定义了一个名为unique_copy的函数,其操作类似于unique。
唯一的差别在于:前者接受第三个迭代器实參,用于指定复制不反复元素的目标序列。
unique_copy依据字面意思就是去除反复元素再运行copy运算。
编敲代码使用unique_copy将一个list对象中不反复的元素赋值到一个空的vector对象中。
//使用unique_copy算法
//将一个list对象中不反复的元素赋值到一个空的vector对象中
#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int ia[7] = {5 , 2 , 2 , 2 , 100 , 5 , 2};
list<int> ilst(ia , ia + 7);
vector<int> ivec;
//将list对象ilst中不反复的元素拷贝到空的vector对象ivec中
//sort(ilst.begin() , ilst.end()); //不能用此种排序。会报错
ilst.sort(); //在进行复制之前要先排序,切记
unique_copy(ilst.begin() , ilst.end() , back_inserter(ivec));
//输出vector容器
cout<<"vector: "<<endl;
for(vector<int>::iterator iter = ivec.begin() ; iter != ivec.end() ; ++iter)
cout<<*iter<<" ";
cout<<endl;
return 0;
}
假如
list<int> ilst(ia , ia + 7); 改为:vector<int> ilst(ia , ia + 7);
则排序时可用:
sort(ilst.begin() , ilst.end());
这里要注意list和vector的排序用什么方法。
《Effective STL》里这些话可能实用处: item 31 “我们总结一下你的排序选择: ● 假设你须要在vector、string、deque或数组上进行全然排序。你能够使用sort或stable_sort。 ● 假设你有一个vector、string、deque或数组,你仅仅须要排序前n个元素,应该用partial_sort。 ● 假设你有一个vector、string、deque或数组。你须要鉴别出第n个元素或你须要鉴别出最前的n个元素,而不用知道它们的顺序,nth_element是你应该注意和调用的。 ● 假设你须要把标准序列容器的元素或数组分隔为满足和不满足某个标准,你大概就要找partition或stable_partition。● 假设你的数据是在list中,你能够直接使用partition和stable_partition,你能够使用list的sort来取代sort和stable_sort。
假设你须要partial_sort或nth_element提供的效果,你就必须间接完毕这个任务,但正如我在上面勾画的。会有非常多选择。
另外,你能够通过把数据放在标准关联容器中的方法以保持在不论什么时候东西都有序。你也可能会考虑标准非STL容器priority_queue,它也能够总是保持它的元素有序。