1、簡介
標准庫容器定義的操作非常少,標准庫沒有給容器添加大量的功能函數,而是選擇提供一組算法,這些算法大都不依賴特定的容器類型,是“泛型”的,可作用在不同類型的容器和不同類型的元素上。
標准容器定義了很少的操作:添加和刪除元素,訪問第一個和最後一個元素,獲取容器的大小,並在某種情況下重設容器的大小,以及獲取指向第一個元素和最後一個元素的下一位置的迭代器。
用戶還希望對容器元素進行更多的其他有用的操作,如:給順序容器中的元素排序或者查找某個特定的元素,或者查找最大或最小的元素等等。標准庫並沒有為每種容器類型都定義實現這些操作的成員函數有的定義了),而是定義了一組“泛型算法”:因為他們實現共同的操作,所以稱之為“算法”,而“泛型”指的是他們可以操作在多種容器類型上---不但可以在vector和list等標准庫類型,也可用在內置數組類型上等。
大多數算法是通過遍歷由兩個迭代器標記的一段元素來實現功能。
2、常用泛型算法
1)find算法(只讀算法)
使用兩個迭代器和一個值調用find函數,檢查兩個迭代器實參標記范圍內的每一個元素,只要找到與給定的值相等,find就會返回指向該元素的迭代器,如果沒有匹配的元素,find返回它的第二個迭代器實參,表示查找失敗。於是,只要檢查函數的返回值是否與它的第二個實參相等,就可得知元素是否找到了。
舉個簡單的例子:
int search_value = 42;
vector<int>::const_iterator result = find(vec.begin(),vec.end(),search_value);
if(result == vec.end())
cout<<"not present"<<endl;
else
cout<<"present"<<endl;
(2)accumulate算法只讀算法)
前兩個形參指定要累加的元素范圍,第三個形參是累加的初值,算法返回累加的結果,返回類型是第三個實參的類型。
舉個簡單的例子:
int sum = accumulate(vec.begin(),vec.end(),42);
string sum = accumulate(v.begin(),v.end(),string(""));
(3)fill算法寫算法)
將值寫入到目標迭代器指定的范圍內。前兩個表示填充的范圍
舉個簡單的例子:
fill(vec.begin(),vec.end(),0);
將vec容器中的所有元素重新賦值為0;
(4)fill_n算法(寫算法)
fill_n(vec.begin(),10,0)
將vec容器開始處的10個元素賦值為0,假如容器為空或當前容器的元素個數少於10個,會出錯。
back_inserter):插入迭代器。使用一個容器對象作為實參。back_inserter生成一個綁定在該容器上的插入迭代器,在試圖通過這個迭代器給元素賦值時,賦值運算將調用push_back在容器中添加一個具有指定值的元素。如下:
vector<int> vec;
fill_n(back_insert(vec),10,0)
這樣就不會出錯,fill_n函數每寫入一個值,都會通過back_inserter生成的插入迭代器實現。效果相當於在vec上調用push_back函數,在vec末尾添加10個元素,每個元素的值均為0。
5)copy算法(寫算法)
vector<int> ivec;
copy(ilst.begin(),ilst.end(),back_inserter(ivec));
將ilst中的所有元素復制給ivec容器中。其實這種效率不高,可在構造新容器的時候用ilst初始化,如:
vector<int> ivec(ilst.begin(),ilst.end());
6)replace算法(寫算法)
帶有4個實參,前兩個實參是替換時查找的范圍,第3個實參是待替換的值,第4個實參是替換值,如:
replace(ilst.begin(),ilst.end(),0,42)
在ilst容器中尋找0,用42代替。
7)replace_copy算法(寫算法)
如果不想改變原來的序列,則調用replace_copy,這個算法接收第3個迭代器實參,指定保存調整後序列的目標位置。
如:
replace_copy(ilst.begin(),ilst.end(),back_inserter(ivec),0,42);
調用該函數後,ilst沒有改變,ivec存儲替換後的副本。
8)sort排序算法
sort(words.begin(),words.end());
容器中的元素按字典順序排列。
9)unique算法:
適合於排序後的容器,刪除相鄰的重復元素。算法返回超出無重復的元素范圍末端的下一位置。
如:
vector<string>::iterator end_unique = unique(words.begin(),words.end());
words.erase(end_unique,words.end());
(10)stable_sort算法
sort算法在給定的范圍內,按照元素的從小到大排列元素。而stable_sort算法,增加了一個參數,稱為謂詞,用來控制根據什麼原則排序。
如:bool IsShort(const string &s1, const string &s2)
{
return s1.size()<s2.size();
}
stable_sort(words.begin(),words.end(),IsShort);
則是根據元素字符串)的長短來排序。
11)count_if算法
記錄滿足某個條件的元素在容器中的數目,也需要謂詞來說明規則。
如:bool GT6(const string &s)
{
return s.size()>=6;
}
vector<string>::size_type wc = count_if(words.begin(),words,end(),GT6);
小結:
容器和算法庫是標准庫的基礎。標准庫定義了超過100個算法,幸運的是,這些算法具有相同的結構,使他們更容易學習和使用。
算法和類型無關,他們通常在一個元素序列上操作,這些元素可以存儲在標准容器類型,內置數組甚至是生成的序列上。
算法基於迭代器操作,從而實現類型無關性。
大多數算法使用一對指定元素范圍的迭代器作為其頭兩個實參,其它的迭代器實參包括指定輸出目標的輸出迭代器,或者用於指定第二個輸入序列的另一個或一對迭代器。
查找某個值的算法通常提供第二個版本,用於查找使謂詞返回非零值的元素。對於這種算法,第二個版本的函數名字已_if後綴表示。類似的,很多算法提供所謂的復制版本,將修改過的)元素寫到輸出序列上,而不是寫回輸入范圍,這種版本的名字已_copy結束。
本文出自 “李海川” 博客,請務必保留此出處http://lihaichuan.blog.51cto.com/498079/1291886