C++學習筆記(十六):對vector進行更多的操作——泛型算法

先強調一下,這裏的泛型算法實際不光光是對vector的操作,對於“順序容器”均可以。

但是什麼是順序容器:

我們都知道,容器就是一些特定類型對象的集合。而順序容器爲程序員提供了控制元素存儲和訪問的能力。這種容器的一個顯著的特徵,就是容器中元素的順序不依賴於元素的值,而是與加入容器時的位置有關。常見的順序容器有vector、deque(雙端隊列)、list(雙向鏈表)、forward_list(單向鏈表)、array(固定大小數組)、string。


瞭解了順序容器,現在以vector爲例,做下文的說明。

順序容器本身只定義了很少的操作,這些操作我在前面的博客(點這裏)也有寫過。比如添加、刪除元素,訪問元素、獲得迭代器等。但是現實中,我們用戶肯定希望有更多的操作供自己使用,比如查找、替換、刪除特定元素,重新排列元素等。爲了實現上面的功能,程序員可能需要寫一大段代碼來將其實現。

爲了解決這個問題,增加對於vector的操作種類,標準庫給出了一組“泛型算法(generic algorithm)”。稱其“算法”,是因爲他們實現了一些經典算法的公共接口,比如排序、搜索。稱其爲“泛型”,是因爲他們可以用於不同類型的元素和多種容器類型。

 

下面講一下具體有哪些泛型算法。

大多數的算法都定義在頭文件algorithm中,標準庫還在頭文件numeric中定義了一組數值泛型算法。一般情況下這些算法並不直接操作容器,而是遍歷由兩個迭代器指定的一個元素範圍。

這些算法大致可以分爲下面幾類:

 

一、只讀算法

顧名思義,這種算法只讀取其輸入範圍內的元素,並不改變元素。

<1>find(vec.begin() , vec.end(), val)

在vec中搜索val,返回第一個等於val的元素的迭代器。如果範圍內無匹配元素,則放回vec.end()。

<2>count(vec.begin() , vec.end(), val)

在vec中搜索val,返回val在vec中出現的次數。

<3>accumulate(vec.begin() , vec.end(), val)

在vec中的元素求和,和的初始值設爲val。val的類型決定了函數使用哪個加法運算符以及返回值類型。

<4>equal(vec1.begin() , vec1.end(), vec2.begin())

比較兩個vector是否相等,返回值爲bool型。

 

二、寫容器元素算法

<1>fill(vec.begin(), vec.end(), val)

將vec中的元素重置爲val


<2>fill_n(dest , n , val)

將從dest開始的n個元素重置爲val。這裏的dest是一個指向某個元素的迭代器。注意:這裏的vec不能是空的,如果是空,那麼上面的操作將會出現未知結果。

 

<3>back_inserter(vec)

向容器中添加元素的迭代器,故稱之爲插入迭代器。通常來說,當我們通過迭代器來給容器賦值時,值被賦予迭代器指向的元素。而當我們通過一個插入迭代器賦值時,一個與賦值號右側值相等的元素被添加到容器中。back_inserter接收一個指向容器的引用,返回一個與該容器綁定的插入迭代器。當我們通過此迭代器賦值時,賦值運算符會調用push_back將一個具有給定值的元素添加到容器中。比如:

vector<int> vec;  //空向量

auto it = back_inserter(vec);  //通過它賦值會將元素添加到vec中

*it = 42;   //vec中現在有一個元素,值爲42

我們常常使用back_inserter來創建迭代器,作爲泛型算法的目的位置使用。比如:

vector<int> vec;   //空向量

fill_n(back_inserter(vec), 10 ,0);  //添加10個元素到vec。

可以發現,前面說fill_n的vec不能爲空,否則將會出現未知結果,而這裏back_inserter相當於給vec push_back 了10個位置,然後填充,故這裏的用法是可以的。

 

<4>copy(vec1.begin(), vec1.end(), vec2.begin())

將vec1中的內容拷貝到vec2中,故這裏要求vec2的長度必須要大於等於vec1的長度。

 

<5>replace(vec.begin(), vec.end(), val1 ,val2)

將vec中的所有val1都替換爲val2。


<6>replace_copy(vec1.begin(), vec1.end(),vec2.begin(), val1 ,val2)

替換後vec1中的值並未改變,而是將vec1拷貝到vec2中,並將vec2中的所有val1都替換爲val2。

 

三、排序

sort(vec.begin() , vec.end());

對vec中的內容按字典順序排序

四、刪除相同數據

unique(vec.begin(), vec.end());

將vec中重複的數據刪除,返回指向不重複區域之後一個位置的迭代器。值得注意的是這個刪除操作只是將vec中的數據清空,但是vec的大小不變。即假設原vec中有40個元素,其中重複的有5個,那麼經過unique操作後,這些重複元素重複的部分就不見了,vec中非空數據變成了35個,剩下的5個空間裏面的數據爲空。但是vec的size仍舊爲40。要想真正的刪除這些元素,還需用到容器本身的操作,erase。

發佈了65 篇原創文章 · 獲贊 366 · 訪問量 60萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章