標籤:泛型演算法 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。
C++學習筆記(十六):對vector進行更多的操作——泛型演算法