去重函式unique,sort,erase
std::unique
一.總述
unique函式屬於STL中比較常用函式,它的功能是元素去重。即”刪除”序列中所有相鄰的重複元素(只保留一個)。此處的刪除,並不
是真的刪除,而是指重複元素的位置被不重複的元素給佔領了。由於它”刪除”的是相鄰的重複元素,所以在使用unique函式之前,一般都
會將目標序列進行排序。
功能:對有序的容器重新排列,將第一次出現的元素從前往後排,其他重複出現的元素依次排在後面
二.函式原型
unique函式的函式原型如下:1.只有兩個引數,且引數型別都是迭代器:
iterator unique(iterator it_1,iterator it_2);
這種型別的unique函式是我們最常用的形式。其中這兩個引數表示對容器中[it_1,it_2)範圍的元素進行去重(注:區間是前閉後開,即不包含it_2所指的元素),返回值是一個迭代器,它指向的是去重後容器中不重複序列的最後一個元素的下一個元素。
有序的容器:
1 | 1 | 2 | 3 | 3 | 4 | 4 | 4 | 5 | 6 |
unique處理過的容器:
unique | unique | unique | unique | unique | unique | 迭代器指向的地址 | |||
1 | 2 | 3 | 4 | 5 | 6 | 1 | 3 | 4 | 4 |
三、去重函式unique
標頭檔案:#include <algorithm>
unique
的作用就是"去除"
陣列中重複的元素,unique去重的過程是將重複的元素移到容器的後面去,實際上這種說法並不正確,應該是把不重複的元素移到前面來:
#include <iostream> #include <algorithm> using namespace std; int main() { int a[10] = { 0, 7, 7, 6, 1, 1, 5, 5, 8, 9 }; int n = unique(a, a + 10) - a; cout << n << endl; //7,得到不重複元素的個數; for (int i = 0; i < 10; i++) cout << a[i] << " "; //0 7 6 1 5 8 9 5 8 9 return 0; }
可以看見最後三個元素是:5 8 9
,而重複的數字是1 5 7
,所以網上這種說法:“unique去重的過程是將重複的元素移到容器的後面去”是不對的
。
上面的n
返回的是7
,它就是:最後一個不重複數字的下標
。
所以,把上面的for
迴圈改成:
for (int i = 0; i < n; i++)
cout << a[i] << " "; //0 7 6 1 5 8 9
讓i < n
就是隻輸出前面不重複的數字,這樣就實現的去重的效果。
四、去重函式unique
與排序函式sort
結合
如果先去重
再排序
那麼結果就是:去重毫無作用。因為去重
再排序
排序時會把重複的數字又放在了一起,所以要先排序
再去重
。這點應該好理解,這裡就提一下。
先排序
再去重
程式碼如下:
#include <iostream>
#include <algorithm> //sort(), unique()
#include <functional> //less<int>()
using namespace std;
int main()
{
int i;
int a[10] = { 0, 7, 7, 6, 1, 1, 5, 5, 8, 9 };
sort( a, a + 10, less<int>() ); //排序
int n = unique(a, a + 10) - a; //去重
for ( i = 0; i < n; i++) //注意i < n
cout << a[i] << " "; //0 1 5 6 7 8 9
}
於是就得到了想要的結果:先把數字排序,再
去掉重複數字。
五,以上便是去重應用於陣列的情況:接下來看一下字串的情況:
uniqe()函式是去掉重複的字元。是指兩個字元連續出現就只留下一個,其餘的就刪除。例如:
string s("hello,world");
string::iterator iterEnd=unique(s.begin(),s.end()); //返回出現重複元素的迭代器位置
這程式碼執行後,s的值為helo,worldd. 只消除連續出現的同樣的字元。重點是不連續的不消除。
unique函式通常和erase函式一起使用,來達到刪除重複元素的目的。(注:此處的刪除是真正的刪除,即從容器中去除重複的元素,容器
的長度也發生了變換;而單純的使用unique函式的話,容器的長度並沒有發生變化,只是元素的位置發生了變化)
還有一個就是unqiue()函式刪除重複的字元後,字串長度不變,所以如果字串刪除字元後,後面按照之前的值填上。 所以就是helo,worldd,而不是helo,world;
所以就會有一個函式erase()函式存在的必要性了。它可以刪除字元。
s.erase(iterEnd,s.end()); //刪除掉重複元素;
執行後s的值就是我們想要的helo,world.
如果想要只留下一個字元l,只能先排序!!!!讓他們挨在一塊。
sort()函式是排序字串字元。 即如果是akjsc,排序後為acjks.
所以一般用unique函式的時候都會用到erase(). sort()用到也也比較多。
六,總結:
#include <iostream>
#include <algorithm> //sort(), unique()
#include <functional> //less<int>()
#include<string>
using namespace std;
int main()
{
/////////////////字串的去重排序
string str = "sjscncmkzmxkz";
sort(str.begin(), str.end()); //先對字串排序;
string::iterator itend = unique(str.begin(), str.end()); //返回出現重複元素的首地址;
cout << str << endl;
str.erase(itend, str.end()); //刪除重複元素;
cout << str << endl;
////////////陣列的去重排序;
int a[10] = { 0, 7, 7, 6, 1, 1, 5, 5, 8, 9 };
sort(a, a + 10, less<int>()); //排序
int n = unique(a, a + 10) - a; //去重
int n1 = distance(a, unique(a, a + n)); //獲得不重複元素的個數;
for (int i = 0; i < n1; i++) //注意i < n
cout << a[i] << " "; //0 1 5 6 7 8 9
}