1、泛型演算法初始
標準庫演算法都是對乙個範圍內的元素進行操作(除了少數例外)。並將此範圍稱為「輸入範圍」,而且總是使用前兩個引數來表示次範圍,這兩個引數分別代表,要處理的首元素和尾元素之後位置的迭代器。
1.1、唯讀演算法
只會讀取輸入範圍內的元素,而從不改變元素
find
int sum = accumulate(c.begin(),c.end(),0);
string sum = accmulate(strc.begin(),strc.end(),string(""));
string sum = accmulate(strc.begin(),strc.end(),"");//錯誤
對於唯讀,不改變元素的演算法,通常使用cbegin(),cend()
操作兩個序列的演算法
//c2的元素數目至少應該等於c1。
//equal(c1.begin(),c1.end(),c2.begin());
1.2、寫容器元素演算法
演算法不會執行容器操作,因此它們不可能改變容器大小。
fill(c.begin(),c.end(),0);//用0填充。
fill(c.begin(),c.size(),0);
//插入迭代器
//back_inserter
vector
vec;
auto it = back_inserter(vec);
*it = 42;
//常常用back_inserter建立乙個迭代器
fill_n(back_inserter(vec),vec.size(),0);
拷貝演算法
//copy
int a1 = ;
int a2[sizeof(a1)/sizeof(*a1)];
auto ret = copy(begin(a1),end(a1),a2);
//replace
replace(c.begin(),c.end(),0,5);//將序列c中的0替換為5
//replace_copy,不改變原來的序列
replace_copy(c.begin(),c.end,back_inserter(ivec),0,5);//ivec是c的拷貝。
1.3、排序演算法
sort(c.begin(),c.end());//對列表c中的元素重新排序
auto end_unique = unique(c.begin(),c.end()); //消除重複元素
2、定製操作
2.1、向演算法傳遞函式
bool isshorter(const
string &s1, const
string &s2)
sort(c.begin(),c.end(),issorter);
2.2、lambda表示式
乙個lambda表示式表示乙個可呼叫的**單元。我們可以將其理解為乙個未命名的內聯函式。
[capture list](parameter list) -> return type
[捕獲列表]為lambda所在函式中定義的區域性變數的列表(通常為空)
(形參列表) 引數列表
return type 返回型別
function body 函式體
(const
string &s1,const
string s2);
隱式捕獲
[=](const string &s1);//=表示值捕獲方式
[&](const string &s1);//&引用捕獲
//混合使用隱式捕獲和顯式捕獲,&隱式捕獲,引用捕獲,c顯式捕獲,值捕獲
[&,c](const string &s);
使用混合捕獲方式時,捕獲方式不能相同。即,隱式捕獲為值捕獲時,顯式捕獲必須為引用捕獲方式。
可變lambda
size_t v1 = 42;
auto f= [v1]()mutable;
指定lambda返回型別
(int i) -> int;
2.3、引數繫結
bind函式
//arg_list是用逗號分隔的引數列表。對應給定的callable的引數。
auto newcallable = bind(callable, arg_list);
auto check6 = bind(check_size, _1,6);
string s = "hello";
bool b1 = check6(s);//呼叫check6(s)時會呼叫check_size(s,6);
使用placeholders名字
名字_n都定義在乙個名為placeholders的命名空間中,這個命名空間本身定義在std命名空間中。為了使用這些名字,兩個命名空間都要寫上。bind、placeholders都定義在functional標頭檔案中。
3、迭代器
3.1、插入迭代器
back_inserter
front_inserter
inserter
3.2、iostream 迭代器
istream_iterator讀取輸入流
ostream_iterator輸出流寫資料
istream_iterator int_it(cin); //從cin讀取int
istream_iterator eof; //尾後迭代器
vector
vec(int_it,eof);
vector
::iterator myiter;
for(myiter = vec.begin();myiter!=vec.end();myiter++)
注:eof被定義為空迭代器,對於乙個繫結到流的迭代器,一旦其關聯的流遇到檔案尾或遇到io錯誤,迭代器的值就與尾後迭代器相等。
//輸出流操作
const
char *str = ;
ostream_iterator out_iter(cout,"\n");
for(int i = 0;i<5;i++)
3.3、反向迭代器
反向迭代器是在容器中從尾元素向首元素反向移動的迭代器。
在反向迭代器中遞增遞減操作的含義會跌倒過來。
遞增乙個反向迭代器(++it)會移動到前乙個元素;遞減乙個反向迭代器會移動到乙個元素。
//反向迭代器
int arr = ;
size_t size = sizeof(arr)/sizeof(int);
vector
vet_int(arr,arr+size);
vector
::reverse_iterator iter;
for(iter = vet_int.rbegin();iter!=vet_int.rend();iter++)
4、泛型演算法結構
4.1、5類迭代器
演算法所要求的迭代器操作可以分為5個迭代器類別
第二種演算法分類方式是按照是否讀、寫或者重排序序列中的元素
4.2、演算法形參模式
大多數演算法具有如下4中形式
//alg演算法名字
alg(beg,end,other args);
alg(beg,end,dest,other args);
alg(beg,end,beg2,other args);
alg(beg,end,beg2,end2,other args);
4.3、演算法命名規範
一些演算法使用過載形式傳遞乙個謂詞
unique(beg,end);//使用==運算子比較元素
unique(beg,end,compare);//使用compare比較
_if版本的演算法
接受乙個元素值的演算法通常有乙個不同名的版本,該版本接受乙個謂詞代替元素
find(beg,end,val);//查詢範圍內val第一次出現的位置
find(beg,end,pred);//查詢第乙個令pred為真的元素
//都是用來查詢出現的位置
區分拷貝版和非拷貝版
reverse(beg,end);//不拷貝,只反轉
reverse_copy(beg,end,dest);//逆序拷貝到dest
5、特定容器的演算法
list, forward_list定義了獨有的sort, merge, remove, reverse 和 unique。通用版本要求隨機反問迭代器,因此不能用於list和forwar_list。
對於list和forward_list應該優先使用成員函式版本的演算法而不是通用演算法
C 泛型演算法
標準庫並未給每個容器都定義成員函式來實現這些操作,而是定義了一組泛型演算法,稱他們為演算法是因為他們實現了一些經典演算法的公共介面,如排序和搜尋 稱他們為排序的是因為它們可以用於不同型別的元素和多種容器型別。大多數演算法都定義在標頭檔案algorithm中。標準庫還在標頭檔案numeric中定義了一...
C 泛型演算法
1 泛型演算法定義 泛型演算法 因為它們實現共同的操作,所以稱之為 演算法 而 泛型 指的是它們可以操作在多種容器型別上 不但可作用於 vector 或 list 這些標準 庫型別,還可用在內建陣列型別 甚至其他型別的序列上,這些我們將在本章的 後續內容中了解。自定義的容器型別只要與標準庫相容,同樣...
c 泛型演算法
泛型演算法都定義在標頭檔案algorithm中,演算法並不直接操作容器,而是遍歷由兩個迭代器指定的乙個元素範圍。find操作的是迭代器,因此我們可以用同樣的find函式在任何容器中查詢值 vector a int val 3 auto result find a.begin a.end val co...