1. 程式人生 > >去重函式unique,sort,erase

去重函式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
}