這周的課講了將泛型算法。現在將泛型算法收集下,備用。
(1)泛型算法用迭代器來解決第一個要求:遍歷容器。所有迭代器都支持自增操作符,從一個元素定位下一個元素,并提供解引用操作符訪問元素的值?
(2)算法也許會改變存儲在容器中的元素的值,也許會在容器內移動元素,但是,算法從不直接添加或刪除元素。??
【 只讀算法】?
?(3)只讀算法是 accumulate,該算法在 numeric 頭文件中定義。? accumulate 帶有三個形參。頭兩個形參指定要累加的元素范圍。第三個形參則是累加的初值。 假設 vec 是一個 int 型的 vector 對象,下面的代碼:? ? ??
// sum the elements in vec starting the summation with the value 42? ? ??
int sum = accumulate(vec.begin(), vec.end(), 42);
?將 sum 設置為 vec 的元素之和再加上 42。 首先,調用該函數時必須傳遞一個起始值,否則,accumulate 將不知道使用什么起始值。 其次,容器內的Section 11.2.? A First Look at the Algorithms元素類型必須與第三個實參的類型匹配,或者可轉換為第三個實參的類型。?
(4) find_first_of 函數。? ? 這個算法帶有兩對迭代器參數來標記兩段元素范圍,在第一段范圍內查找與第二段范圍中任意元素匹配的元素,然后返回一個迭代器,指向第一個匹配的元素。如果找不到元素,則返回第一個范圍的 end 迭代器。? ? ??
size_t cnt = 0;? ? ?
?list::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;
? ? 注意:find_first_of,帶有兩對迭代器參數。每對迭代器中,兩個實參的類型必須精確匹配,但不要求兩對之間的類型匹配。特別是,元素可存儲在不同類型序列中,只要這兩序列的元素可以比較即可。?
?【 寫容器元素的算法】**********************************************************?
?(5) fill 函數,寫入到輸入序列的算法? ? fill 帶有一對迭代器形參,用于指定要寫入的范圍,而所寫的值是它的第三個形參的副本。執行時,將該范圍內的每個元素都設為給定的值。如果輸入范圍有效,則可安全寫 入。這個算法只會對輸入范圍內已存在的元素進行寫入操作。
? ? ?fill(vec.begin(), vec.end(), 0);?// reset each element? to 0 ? ? ?
// set? subsequence of the range to 10
? ? ? fill(vec.begin(), vec.begin() + vec.size()/2, 10);?
(6) fill_n函數,不檢查寫入操作的算法? ? fill_n 函數帶有的參數包括:一個迭代器、一個計數器以及一個值。該函數從迭代器指向的元素開始,將指定數量的元素設置為給定的值。fill_n 函數假定對指定數量的元 素做寫操作是安全的。? ? 注意:初學者常犯的錯誤的是:在沒有元素的空容器上調用 fill_n 函數(或者類似的寫元素算法):? ? ??
*****************************************************
? ? ? vectorvec; // empty vector
? ? ? // disaster: attempts to write to 10 (nonexistent) elements in vec
? ? ? fill_n(vec.begin(), 10, 0);
? ? ? //vec 是空的,其結果未定義,很可能導致嚴重的運行時錯誤。? ? ? *****************************************************
?(7) copy 函數,寫入到目標迭代器的算法? ? copy 帶有三個迭代器參數:頭兩個指定輸入范圍,第三個則指向目標序列的一個元素。傳遞給 copy 的目標序列必須至少要與輸入范圍一樣大。? ? 假設 ilst 是一個存放 int 型數據的 list 對象,可如下將它 copy 給一個 vector 對象:
? ? vectorivec; // empty vector
? ? // copy elements from ilst into ivec
? ? copy (ilst.begin(), ilst.end(), back_inserter(ivec));
?(8)算法的 _copy 版本? 有些算法提供所謂的“復制(copying)”版本。這些算法對輸入序列的元素做出處理,但不修改原來的元素,而是創建一個新序列存儲元素的處理結果。但不修改原來的元素, 而是創建一個新序列存儲元素的處理結果。
?(9)replace 算法,對輸入序列做讀寫操作,將序列中特定的值替換為新的值? 該算法帶有四個形參:一對指定輸入范圍的迭代器和兩個值。每一個等于 第一值的元素替換成第二個值。
? ? ? // replace any element? with value of 0 by 42
? ? ? replace(ilst.begin(), ilst.end(), 0, 42);?
(10)replace_copy? ? 這個算法接受第三個迭代器實參,指定保存調整后序列的目標位置。
? ? ? // create empty vector to hold the replacement? ? ? vector<i>ivec;
? ? ? // use back_inserter to grow destination as needed
? ? ? replace_copy (ilst.begin(), ilst.end(),back_inserter(ivec), 0, 42);
? ? 調用該函數后,ilst 沒有改變,ivec 存儲 ilst 一份副本,而 ilst 內所有的 0 在 ivec 中都變成了 42。??
【 對容器元素重新排序的算法】**************************************************
?(11)sort 算法? ? sort 算法帶有兩個迭代器實參,指出要排序的元素范圍。這個算法使用小于(<)操作符比較元素。
?(12)unique 算法,該算法刪除相鄰的重復元素,然后重新排列輸入范圍內的元素,并且返回一個迭代器,表示無重復的值范圍的結束。? ? 它帶有兩個指定元素范圍的迭代器參數。? ? 注:調用 unique“刪除”了相鄰的重復值。給“刪除”加上引號是因為 unique 實際上并沒有刪除任何元素,而是將無重復的元素復制到序列的前端,從而覆蓋相鄰的重復元素。unique 返回的迭代器指向超出無重復的元素范圍末端的下一位置。(想真正刪除元素要與erase函數連用)
?(13)stable_sort 算法,有著相同長度的元素還能以字典次序的不同而區分? ? stable_sort 算法有第三個形參:比較元素所使用的謂詞函數的名字。這個謂詞函數必須接受兩個實參,實參的類型必須與元素類型相同,并返回一個可用作條件檢測的值。
? ? ? // sort words by size,? but? maintain alphabetic order for words of the same size? ? ? stable_sort(words.begin(), words.end(), isShorter);?
?? ? // comparison function to be used to sort? by word length
? ? ? bool isShorter(const string &s1, const string &s2)
? ? ? {
? ? ? ? ? return s1.size() < s2.size();
? ? ? }
?(14)count_if 算法,統計個數? ? 執行 count_if 時,首先讀取它的頭兩個實參所標記的范圍內的元素。每讀出一個元素,就將它傳遞給第三個實參表示的謂詞函數。此謂詞函數。此謂詞函數需要單個元素類型 的實參,并返回一個可用作條件檢測的值。count_if 算法返回使謂詞函數返回條件成立的元素個數。? ? ? vector::size_type wc =count_if(words.begin(), words.end(), GT6);
? ? ? // determine whether a length of a given word is 6 or more
? ? ? bool GT6(const string &s)
? ? ? {?
?? ? ? ? return s.size() >= 6;
? ? ? }
? 【 再談迭代器】****************************************************************?
?(15)插入迭代器(insert iterators):這類迭代器與容器綁定在一起,實現在容器中插入元素的功能。? 插入器是一種迭代器適配器,帶有一個容器參數,并生成一個迭代器,用于在指定容器中插入元素。通過插入迭代器賦值時,迭代器將會插入一個新的元素。C++ 語言提供了三種插入器,其差別在于插入元素的位置不同:
?(a)back_inserter,創建使用 push_back 實現插入的迭代器。
?(b)front_inserter,使用 push_front 實現插入。
? (c)inserter,使用 insert 實現插入操作。除了所關聯的容器外,inserter 還帶有第二實參:
? ? ? 指向插入起始位置的迭代器。
?注:front_inserter 需要使用 push_front,只有當容器提供 push_front 操作時,才能使用 front_inserter。在 vector 或其他沒有 push_front 運算的容器上使用front_inserter,將產生錯下載文檔到電腦,查找使用更方便1下載券? 131人已下載下載還剩2頁未讀,繼續閱讀誤。
? ? ? listilst, ilst2, ilst3;
? ? // empty lists
? ? ? // after this loop ilst contains: 3 2 1 0
? ? ? for (list::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()));
?在復制并創建 ilst2 的過程中,元素總是在這個 list 對象的所有元素之前插入。而在復制創建 ilst3 的過程中,元素則在 ilst3 中的固定位置插入。剛開始時,這個插入 位置是此 list 對象的頭部,但插入一個元素后,就不再是首元素了。
? (16) iostream 迭代器
? ? 【注】流迭代器都是類模板:任何已定義輸入操作符(>> 操作符)的類型都可以定義 istream_iterator。類似地,任何已定義輸出操作符(<< 操作符)的類型也可定義ostream_iterator。
? ? ? istream_iteratorcin_it(cin);? ? // reads ints1 from cin
? ? ? istream_iteratorend_of_stream;? // end iterator value
? ? ? // writes Sales_items from the ofstream named outfile
? ? ? // each element? is followed by a space? ? ? ofstream outfile;?
在創建 istream_iterator 時,可直接將它綁定到一個流上。另一種方法是在創建時不提供實參,則該迭代器指向超出末端位置。ostream_iterator 不提供超出末端迭代器。 在創建 ostream_iterator 對象時,可提供第二個(可選的)實參,指定將元素寫入輸出流時使用的分隔符。分隔符必須是 C 風格字符串。因為它是 C 風格字符串,所以必須以空字符結束;否則,其行為將是未定義的。
? ? 【注】流迭代器的限制:
?(a)不可能從 ostream_iterator 對象讀入,也不可能寫到 istream_iterator 對象中。
?(b)一旦給 ostream_iterator 對象賦了一個值,寫入就提交了。賦值后,沒有辦法再改變這個值。此外,ostream_iterator 對象中每個不同的值都只能正好輸出一次。
?(c)ostream_iterator 沒有 -> 操作符。
? ? ? istream_iteratorcin_it(cin);? ? // reads ints from cin
? ? ? istream_iteratorend_of_stream;? // end iterator value
? ? ? // initialize vec from the standard input:
? ? ? vectorvec(cin_it, end_of_stream);
? ? ? sort(vec.begin(), vec.end());
? ? ? // writes ints to cout using " " as the delimiter
? ? ? ostream_iterator<int>output(cout, " ");
//?write?only?the?unique?elements?in?vec?to?the?standard?output
?? ? unique_copy(vec.begin(),?vec.end(),?output);
輸入是:?23?109?45?89?6?34?12?90?34?23?56?23?8?89?23?輸出是:?6?8?12?23?34?45?56?89?90?109