一,、只讀算法 1,、使用兩個迭代器和一個值調(diào)用 find 函數(shù),檢查兩個迭代器實參標記范圍內(nèi)的每一個元素,。只要找到與給定值相等的元素,,find 就會返回指向該元素的迭代器,。如果沒有匹配的元素,find 就返回它的第二個迭代器實參,,表示查找失敗,。于是,只要檢查該函數(shù)的返回值是否與它的第二個實參相等,,就可得知元素是否找到了,。 int search_value = 42; // call find to see if that value is present vector<int>::const_iterator result = find(vec.begin(), vec.end(), search_value); // report the result cout << "The value " << search_value << (result == vec.end()? " is not present" : " is present") << endl; 2、許多算法只會讀取其輸入范圍內(nèi)的元素,,而不會寫這些元素,。find 就是一個這樣的算法。另一個簡單的只讀算法是 accumulate,,accumulate 帶有三個形參,。頭兩個形參指定要累加的元素范圍。第三個形參則是累加的初值,。 // sum the elements in vec starting the summation with the value 42 int sum = accumulate(vec.begin(), vec.end(), 42); // concatenate elements from v and store in sum string sum = accumulate(v.begin(), v.end(), string("")); 3,、find_first_of 函數(shù)。這個算法帶有兩對迭代器參數(shù)來標記兩段元素范圍,,在第一段范圍內(nèi)查找與第二段范圍中任意元素匹配的元素,,然后返回一個迭代器,指向第一個匹配的元素,。如果找不到元素,,則返回第一個范圍的 end 迭代器。假設 roster1 和 roster2 是兩個存放名字的 list 對象,,可使用 find_first_of 統(tǒng)計有多少個名字同時出現(xiàn)在這兩個列表中: size_t cnt = 0; list<string>::iterator it = roster1.begin(); // look in roster1 for any name also in roster2 while ((it = find_first_of(it, roster1.end(),roster2.begin(), roster2.end())) != roster1.end()) { ++cnt; // we got a match, increment it to look in the rest of roster1 ++it; } cout << "Found " << cnt << " names on both rosters" << endl; 二,、寫容器元素的算法 1、寫入到輸入序列的算法本質(zhì)上是安全的——只會寫入與指定輸入范圍數(shù)量相同的元素,,fill 帶有一對迭代器形參,,用于指定要寫入的范圍,而所寫的值是它的第三個形參的副本,。執(zhí)行時,,將該范圍內(nèi)的每個元素都設為給定的值。如果輸入范圍有效,,則可安全寫入,。這個算法只會對輸入范圍內(nèi)已存在的元素進行寫入操作。 // reset each element to 0 fill(vec.begin(), vec.end(), 0); // set subsequence of the range to 10 fill(vec.begin(), vec.begin() + vec.size()/2, 10); 2,、fill_n 函數(shù)帶有的參數(shù)包括:一個迭代器,、一個計數(shù)器以及一個值。該函數(shù)從迭代器指向的元素開始,,將指定數(shù)量的元素設置為給定的值,。fill_n 函數(shù)假定對指定數(shù)量的元素做寫操作是安全的,。初學者常犯的錯誤的是:在沒有元素的空容器上調(diào)用 fill_n 函數(shù)(或者類似的寫元素算法)。 vector<int> vec; // empty vector // disaster: attempts to write to 10 (nonexistent) elements in vec fill_n(vec.begin(), 10, 0); 3,、確保算法有足夠的元素存儲輸出數(shù)據(jù)的一種方法是使用插入迭代器。插入迭代器是可以給基礎容器添加元素的迭代器,。通常,,用迭代器給容器元素賦值時,被賦值的是迭代器所指向的元素,。而使用插入迭代器賦值時,,則會在容器中添加一個新元素,其值等于賦值運算的右操作數(shù)的值,。 back_inserter 函數(shù)是迭代器適配器,。與容器適配器一樣,迭代器適配器使用一個對象作為實參,,并生成一個適應其實參行為的新對象,。本例中,傳遞給 back_inserter 的實參是一個容器的引用,。back_inserter 生成一個綁定在該容器上的插入迭代器,。在試圖通過這個迭代器給元素賦值時,賦值運算將調(diào)用 push_back 在容器中添加一個具有指定值的元素,。 vector<int> vec; // empty vector // ok: back_inserter creates an insert iterator that adds elements to vec // appends 10 elements to vec fill_n (back_inserter(vec), 10, 0); 4,、向目標迭代器寫入未知個數(shù)的元素。正如 fill_n 函數(shù)一樣,,目標迭代器指向存放輸出數(shù)據(jù)的序列中第一個元素,。這類算法中最簡單的是 copy 函數(shù)。copy 帶有三個迭代器參數(shù):頭兩個指定輸入范圍,,第三個則指向目標序列的一個元素,。傳遞給 copy 的目標序列必須至少要與輸入范圍一樣大。假設 ilst 是一個存放 int 型數(shù)據(jù)的 list 對象,,可如下將它 copy 給一個 vector 對象: vector<int> ivec; // empty vector // copy elements from ilst into ivec copy (ilst.begin(), ilst.end(), back_inserter(ivec)); 5,、有些算法提供所謂的“復制(copying)”版本。這些算法對輸入序列的元素做出處理,,但不修改原來的元素,,而是創(chuàng)建一個新序列存儲元素的處理結(jié)果。但不修改原來的元素,,而是創(chuàng)建一個新序列存儲元素的處理結(jié)果,。replace 算法就是一個很好的例子。該算法對輸入序列做讀寫操作,,將序列中特定的值替換為新的值,。該算法帶有四個形參:一對指定輸入范圍的迭代器和兩個值,。每一個等于第一值的元素替換成第二個值。 // replace any element with value of 0 by 42 replace(ilst.begin(), ilst.end(), 0, 42); // create empty vector to hold the replacement vector<int> ivec; // use back_inserter to grow destination as needed //every element in ilst with the value 0 has the value 42 in ivec replace_copy (ilst.begin(), ilst.end(), back_inserter(ivec), 0, 42); 三,、對容器元素重新排序的算法 1,、unique 算法帶有兩個指定元素范圍的迭代器參數(shù)。該算法刪除相鄰的重復元素,,然后重新排列輸入范圍內(nèi)的元素,,并且返回一個迭代器,表示無重復的值范圍的結(jié)束,。 // sort words alphabetically so we can find the duplicates //words:the quick red fox jumps over the slow red turtle sort(words.begin(), words.end()); vector<string>::iterator end_unique = unique(words.begin(), words.end()); words.erase(end_unique, words.end()); 2,、如果要刪除重復的項,必須使用容器操作,,在本例中調(diào)用 erase 實現(xiàn)該功能,。這個函數(shù)調(diào)用從 end_unique 指向的元素開始刪除,直到 words 的最后一個元素也刪除掉為止,。 3,、sort和stable_sort 算法,,,stable_sort 保留相等元素的原始相對位置,。sort 和 stable_sort 都是重載函數(shù)。其中一個版本使用元素類型提供的小于(<)操作符實現(xiàn)比較,。在查找重復元素之前,,我們就是用這個 sort 版本對元素排序。第二個重載版本帶有第三個形參:比較元素所使用的謂詞函數(shù)的名字,。這個謂詞函數(shù)必須接受兩個實參,,實參的類型必須與元素類型相同,并返回一個可用作條件檢測的值,。 sort(words.begin(), words.end()); // sort words by size, but maintain alphabetic order for words of the same size stable_sort(words.begin(), words.end(), isShorter); 4,、統(tǒng)計滿足指定條件的項數(shù)。執(zhí)行 count_if 時,,首先讀取它的頭兩個實參所標記的范圍內(nèi)的元素,。每讀出一個元素,就將它傳遞給第三個實參表示的謂詞函數(shù),。此謂詞函數(shù),。此謂詞函數(shù)需要單個元素類型的實參,并返回一個可用作條件檢測的值,。count_if 算法返回使謂詞函數(shù)返回條件成立的元素個數(shù),。 //GT6 returns a bool value vector<string>::size_type wc = count_if(words.begin(), words.end(), GT6); 四、泛型算法中使用迭代器 1,、插入迭代器 1.1 back_inserter,,創(chuàng)建使用 push_back 實現(xiàn)插入的迭代器,。 1.2 front_inserter,使用 push_front 實現(xiàn)插入,。該函數(shù)將創(chuàng)建一個迭代器,,調(diào)用它所關聯(lián)的基礎容器的 push_front 成員函數(shù)代替賦值操作。只有當容器提供 push_front 操作時,,才能使用 front_inserter,。在 vector 或其他沒有 push_front 運算的容器上使用 front_inserter,將產(chǎn)生錯誤,。 1.3 inserter,使用 insert 實現(xiàn)插入操作,。這種適配器帶有兩個實參:所關聯(lián)的容器和指示起始插入位置的迭代器,。 // position an iterator into ilst list<int>::iterator it = find (ilst.begin(), ilst.end(), 42); // insert replaced copies of ivec at that point in ilst replace_copy (ivec.begin(), ivec.end(), inserter (ilst, it), 100, 0); 1.4 也許我們會認為可使用 inserter 和容器的 begin 迭代器來模擬 front_inserter 的效果。然而,,inserter 的行為與 front_inserter 的有很大差別,。在使用 front_inserter 時,元素始終在容器的第一個元素前面插入,。而使用 inserter 時,,元素則在指定位置前面插入。即使此指定位置初始化為容器中的第一個元素,,但是,,一旦在該位置前插入一個新元素后,插入位置就不再是容器的首元素了: list<int> ilst, ilst2, ilst3; // after this loop ilst contains: 3 2 1 0 for (list<int>::size_type i = 0; i != 4; ++i) ilst.push_front(i); // after copy ilst2 contains: 0 1 2 3 copy (ilst.begin(), ilst.end(), front_inserter(ilst2)); // after copy, ilst3 contains: 3 2 1 0 copy (ilst.begin(), ilst.end(), inserter (ilst3, ilst3.begin())); 2,、iostream 迭代器 雖然 iostream 類型不是容器,,但標準庫同樣提供了在 iostream 對象上使用的迭代器: istream_iterator用于讀取輸入流,而ostream_iterator則用于寫輸出流,。這些迭代器將它們所對應的流視為特定類型的元素序列,。使用流迭代器時,可以用泛型算法從流對象中讀數(shù)據(jù)(或?qū)?shù)據(jù)寫到流對象中),。 2.1 可使用 istream_iterator 對象將標準輸入讀到 vector 對象中,。 istream_iterator<int> in_iter(cin); // read ints from cin istream_iterator<int> eof; // istream "end" iterator // read until end of file, storing what was read in vec while (in_iter != eof) // increment advances the stream to the next value // dereference reads next value from the istream vec.push_back(*in_iter++); 2.2 可使用 ostream_iterator 對象將一個值序列寫入流中,其操作的過程與使用迭代器將一組值逐個賦給容器中的元素相同: // write one string per line to the standard output ostream_iterator<string> out_iter(cout, "\n"); // read strings from standard input and the end iterator istream_iterator<string> in_iter(cin), eof; // read until eof and write what was read to the standard output while (in_iter != eof) // write value of in_iter to standard output // and then increment the iterator to get the next value from cin *out_iter++ = *in_iter++; 2.3 流迭代器d的幾個重要限制: 不可能從 ostream_iterator 對象讀入,,也不可能寫到 istream_iterator 對象中,。 一旦給 ostream_iterator 對象賦了一個值,寫入就提交了,。賦值后,,沒有辦法再改變這個值。此外,,ostream_iterator 對象中每個不同的值都只能正好輸出一次,。 ostream_iterator 沒有 -> 操作符,。 3、反向迭代器 反向迭代器是一種反向遍歷容器的迭代器,。也就是,,從最后一個元素到第一個元素遍歷容器。反向迭代器將自增(和自減)的含義反過來了:對于反向迭代器,,++ 運算將訪問前一個元素,,而 -- 運算則訪問下一個元素。 // reverse iterator of vector from back to front vector<int>::reverse_iterator r_iter; for (r_iter = vec.rbegin(); // binds r_iter to last element r_iter != vec.rend(); // rend refers 1 before 1st element ++r_iter) // decrements iterator one element cout << *r_iter << endl; // prints 9,8,7,...0 4,、const 迭代器 在之前使用 find 的程序中,,我們將 result 定義為 const_iterator 類型。這樣做是因為我們不希望使用這個迭代器來修改容器中的元素,。find_first_of程序中也不打算改變?nèi)萜鲀?nèi)的任何元素,,但是它卻使用了普通的非 const 迭代器來保存 find_first_of 的返回值。 原因是,,在第二個例子中,,程序?qū)⒌饔米?find_first_of 的實參: find_first_of(it, roster1.end(), roster2.begin(), roster2.end()) 該函數(shù)調(diào)用的輸入范圍由 it 和調(diào)用 roster1.end() 返回的迭代器指定。算法要求用于指定范圍的兩個迭代器必須具有完全一樣的類型,。roster1.end() 返回的迭代器依賴于 roster1 的類型,。如果該容器是 const 對象,則返回的迭代器是 const_iterator 類型,;否則,,就是普通的 iterator 類型。在這個程序中,,roster1 不是 const 對象,,因而 end 返回的只是一個普通的迭代器。 5,、迭代器分類 Input iterator(輸入迭代器) 讀,,不能寫;只支持自增運算 Output iterator(輸出迭代器) 寫,,不能讀,;只支持自增運算 Forward iterator(前向迭代器) 讀和寫;只支持自增運算 Bidirectional iterator(雙向迭代器) 讀和寫,;支持自增和自減運算 Random access iterator(隨機訪問迭代器) 讀和寫,;支持完整的迭代器算術(shù)運算 |
|
來自: 昵稱14816093 > 《C 》