一.總述html
unique函數屬於STL中比較經常使用函數,它的功能是元素去重。即」刪除」序列中全部相鄰的重複元素(只保留一個)。此處的刪除,並非真的刪除,而是指重複元素的位置被不重複的元素給佔領了(詳細狀況,下面會講)。因爲它」刪除」的是相鄰的重複元素,因此在使用unique函數以前,通常都會將目標序列進行排序。ios
二.函數原型函數
unique函數的函數原型以下:spa
1.只有兩個參數,且參數類型都是迭代器:htm
iterator unique(iterator it_1,iterator it_2);
這種類型的unique函數是咱們最經常使用的形式。其中這兩個參數表示對容器中[it_1,it_2)範圍的元素進行去重(注:區間是前閉後開,即不包含it_2所指的元素),返回值是一個迭代器,它指向的是去重後容器中不重複序列的最後一個元素的下一個元素。blog
2.有三個參數,且前兩個參數類型爲迭代器,最後一個參數類型能夠看做是bool類型:排序
iterator unique(iterator it_1,iterator it_2,bool MyFunc);
該類型的unique函數咱們使用的比較少,其中前兩個參數和返回值同上面類型的unique函數是同樣的,主要區別在於第三個參數。這裏的第三個參數表示的是自定義元素是否相等。也就是說經過自定義兩個元素相等的規則,來對容器中元素進行去重。這裏的第三個參數與STL中sort函數的第三個參數功能相似(關於sort函數:http://www.cnblogs.com/wangkundentisy/p/8982180.html)。關於第三個參數的詳細介紹,能夠參考:http://www.cplusplus.com/reference/algorithm/unique/get
三.函數用法實例原型
上面介紹了unique函數的功能和原型,那麼,它究竟是如何進行去重的呢?即「刪除」的具體操做是怎樣的呢?源碼
關於這個問題,http://www.cplusplus.com/reference/algorithm/unique/給了咱們一種解釋,即unique函數是徹底等價於下面這個函數的:
iterator My_Unique (iterator first, iterator last) { if (first==last) return last; iterator result = first; while (++first != last) { if (!(*result == *first)) *(++result)=*first; } return ++result; }
分析這段代碼,咱們能夠知道,unique函數的去重過程實際上就是不停的把後面不重複的元素移到前面來,也能夠說是用不重複的元素佔領重複元素的位置。有了這段代碼咱們能夠結合實例來更好的理解這個函數了。
實例:
#include<iostream> #include<algorithm> #include<cassert> using namespace std; static bool myfunc(int i, int j) { return (i + 1) == j; //return i == j; } int main() { vector<int> a = {1,3,3,4,5,6,6,7}; vector<int>::iterator it_1 = a.begin(); vector<int>::iterator it_2 = a.end(); //sort(it_1,it_2); cout<<"去重前的 a : "; for(int i = 0 ; i < a.size(); i++) cout<<a[i]; cout<<endl; //it_h = unique(it_1,it_2); //unique(it_1,it_2,myfunc); unique(it_1,it_2); cout<<"去重後的 a : "; for(int i = 0 ; i < a.size(); i++) cout<<a[i]; cout<<endl; }
運行結果以下:
對於上面的結果,咱們能夠看到,容器中不重複的元素都移到了前面,至於後面的元素,實際上並無改變(這個過程只需結合My_Unique函數來分析便可)。
注:
1.有不少文章說的是,unique去重的過程是將重複的元素移到容器的後面去,實際上這種說法並不正確,應該是把不重複的元素移到前面來。
2.必定不要忘記的是,unique函數在使用前須要對容器中的元素進行排序(固然不是必須的,但咱們絕大數狀況下須要這麼作),因爲本例中的元素已是排好序的,因此此處我沒排序,但實際使用中不要忘記。
四.用法拓展
1.咱們以上的實例針對的是函數原型1的用法,對於函數原型2,咱們仍然使用上述實例,只不過unique的用法變成:
unique(it_1,it_2,myfunc);
即自定義的元素相等的準則,其中myfunc在上述實例中有其源碼,分析可知,只有i+1 == j的時候咱們才認爲i和j「相等」;實例結果以下:
也就是說,按照咱們自定義的規則,這個實例中只有3和4」相等的」,4和5是」相等的」,5和6,6和7是」相等的」。因此最終結果是上圖的樣子。
2.unique函數一般和erase函數一塊兒使用,來達到刪除重複元素的目的。(注:此處的刪除是真正的刪除,即從容器中去除重複的元素,容器的長度也發生了變換;而單純的使用unique函數的話,容器的長度並無發生變化,只是元素的位置發生了變化)關於erase函數的用法,能夠參考:http://www.cnblogs.com/wangkundentisy/p/9023977.html。下面是一個具體的實例:
#include<iostream> #include<algorithm> #include<cassert> using namespace std; int main() { vector<int> a ={1,3,3,4,5,6,6,7}; vector<int>::iterator it_1 = a.begin(); vector<int>::iterator it_2 = a.end(); vector<int>::iterator new_end; new_end = unique(it_1,it_2); //注意unique的返回值 a.erase(new_end,it_2); cout<<"刪除重複元素後的 a : "; for(int i = 0 ; i < a.size(); i++) cout<<a[i]; cout<<endl; }
運行結果以下:
能夠看到,相比以前的結果,a的長度確實發生了改變,真正的刪除了a中的重複元素。