第十一章 泛型算法
code:
/* 第11章 泛型算法 11.1 概述 11.2 初窥算法 11.3 再谈迭代器 11.4 泛型算法的结构 11.5 容器特有的算法 小结 第11章 泛型算法 335 11.1 概述 336 11.2 初窥算法 339 11.2.1 只读算法 339 11.2.2 写容器元素的算法 341 11.2.3 对容器元素重新排序的算法 343 11.3 再谈迭代器 347 11.3.1 插入迭代器 348 11.3.2 iostream迭代器 349 11.3.3 反向迭代器 353 11.3.4 const迭代器 355 11.3.5 五种迭代器 356 11.4 泛型算法的结构 358 11.4.1 算法的形参模式 359 11.4.2 算法的命名规范 359 11.5 容器特有的算法 361 小结 362 术语 363 */ // 11.1 概述 ------------------------------------------------------------------------------------------------------------------ #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> using namespace std; int main() { vector<int> vec; // value we'll look for 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; return 0; } #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> using namespace std; int main() { list <int> lst; int search_value = 42; // call find to look through elements in a list list < int > ::const_iterator result = find(lst.begin(), lst.end(), search_value); cout << "The value " << search_value << (result == lst.end() ? " is not present" : " is present") << endl; return 0; } // 第一次在数组上使用泛型算法。把数组当容器看。 #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> using namespace std; int main() { int ia[6] = { 27, 210, 12, 47, 109, 83 }; int search_value = 83; int *result = find(ia, ia + 6, search_value); cout << "The value " << search_value << (result == ia + 6 ? " is not present" : " is present") << endl; result = find(ia, ia + 5, search_value); // 搜索子区间 cout << "The value " << search_value << (result == ia + 5 ? " is not present" : " is present") << endl; return 0; } // 11.2 初窥算法 -------------------------------------------------------------------------------------------------------------- /* 11.2.1. 只读算法 11.2.2. 写容器元素的算法 11.2.3. 对容器元素重新排序的算法 */ //11.2.1. 只读算法 // accumulate #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> using namespace std; int main() { vector<int> vec(3,1); // sum the elements in vec starting the summation with the value 42 int sum = accumulate(vec.begin(), vec.end(), 42); cout << sum << endl; vector<string> v(30,"ha"); // concatenate elements from v and store in sum string s = accumulate(v.begin(), v.end(), string("")); cout << s << endl; return 0; } // in book #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> using namespace std; int main() { list<string> roster1,roster2; // program for illustration purposes only: // there are much faster ways to solve this problem 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; return 0; } // 修改,观察输出 #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> using namespace std; int main() { list<string> roster1,roster2; roster1.insert(roster1.end(),"abc"); roster1.insert(roster1.end(),"def"); roster1.insert(roster1.end(),"test"); // 末尾添加,方便观察 roster2.insert(roster2.end(),"hij"); roster2.insert(roster2.end(),"test"); roster2.insert(roster2.end(),"abc"); 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() ) // 第一次,找roster1中,第一次出现在roster2中的,返回第一个位置,输出"abc" { // 第二次,在第二个位置开始,找出现在roster2中的,返回"test",输出"test" ++cnt; // 第三次,已经到了roster1.end(),退出循环 cout << *it << endl; // 因为是list,所以是顺序查找,这种效率是低的,O(n^2) ++it; } cout << "Found " << cnt << " names on both rosters" << endl; return 0; } // 改进 #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> using namespace std; int main() { vector<string> r1; r1.insert(r1.end(),"abc"); r1.insert(r1.end(),"def"); r1.insert(r1.end(),"test"); // 末尾添加,方便观察 set<string> r2; r2.insert(r2.end(),"hij"); r2.insert(r2.end(),"test"); r2.insert(r2.end(),"abc"); size_t cnt = 0; vector < string > ::iterator it = r1.begin(); while( ( it = find_first_of (it, r1.end(), r2.begin(), r2.end()) ) != r1.end() ) // 第一次,找roster1中,第一次出现在roster2中的,返回第一个位置,输出"abc" { // 第二次,在第二个位置开始,找出现在roster2中的,返回"test",输出"test" ++cnt; // 第三次,已经到了roster1.end(),退出循环 cout << *it << endl; // 第一个容器,改成了vector,第二个容器,改成了set,这样 O(nlogn) ++it; } cout << "Found " << cnt << " names on both rosters" << endl; return 0; } //11.2.2. 写容器元素的算法 #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> using namespace std; int main() { vector<int> vec(8); 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); vector<int>::iterator it=vec.begin(); while( it!=vec.end() ) cout << *it++ << endl; return 0; } // test越界写入。书里说可能会有运行时错误,但木有发生。总之,不鼓励这么做。。 #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> using namespace std; int main() { vector<int> vec(4,0); fill(vec.begin(), vec.begin() + 8, 10); // 第一次越界写入 vector<int>::iterator it=vec.begin(); while( it!=vec.end() ) cout << *it++ << endl; cout << endl; fill_n(vec.begin(),18,1); // 第二次越界写入 it=vec.begin(); while( it!=vec.end() ) cout << *it++ << endl; return 0; } // 插入迭代器 #include <iostream> #include <string> #include <vector> #include <deque> #include <list> #include <stack> #include <queue> #include <utility> #include <map> #include <set> #include <algorithm> #include <numeric> #include <iterator> using namespace std; int main() { vector<int> vec(4,0); fill_n(back_inserter(vec),5,8); // 这样不会越界了 vector<int>::iterator it=vec.begin(); while( it!=vec.end() ) cout << *it++ << ' '; cout << endl; for(int i=0; i<4; ++i) vec.insert(vec.end(),3); // 4 3 it=vec.begin(); // 貌似用insert比较容易理解 while( it!=vec.end() ) cout << *it++ << ' '; cout << endl; return 0; } // copy #include <iostream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { list<int> ilst(3,3); vector<int> vec(3,0); copy(ilst.begin(),ilst.end(),back_inserter(vec)); vector<int>::iterator it=vec.begin(); while( it!=vec.end() ) cout << *it++ << ' '; cout << endl; vector<int> v(ilst.begin(),ilst.end()); it=v.begin(); while( it!=v.end() ) cout << *it++ << ' '; return 0; } // replace_copy #include <iostream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { list<int> ilst(3,3); replace(ilst.begin(),ilst.end(),3,42); list<int>::iterator lit=ilst.begin(); while(lit!=ilst.end()) cout << *lit++ << ' '; cout << endl; vector<int> vec(3,3); replace_copy(ilst.begin(),ilst.end(), back_inserter(vec),42,0); vector<int>::iterator it=vec.begin(); while( it!=vec.end() ) cout << *it++ << ' '; return 0; } //11.2.3. 对容器元素重新排序的算法 // in book // 输出部分还没完成。 // 谓词部分,还木有全懂。。。。。。 #include <iostream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; // comparison function to be used to sort by word length bool isShorter(const string &s1, const string &s2) { return s1.size() < s2.size(); } // determine whether a length of a given word is 6 or more bool GT6(const string &s) { return s.size() >= 6; } int main() { vector < string > words; // copy contents of each book into a single vector string next_word; while(cin >> next_word) { // insert next book's contents at end of words words.push_back(next_word); } // sort words alphabetically so we can find the duplicates sort(words.begin(), words.end()); /* eliminate duplicate words: * unique reorders words so that each word appears once in the * front portion of words and returns an iterator one past the unique range; * erase uses a vector operation to remove the nonunique elements */ vector < string > ::iterator end_unique = unique(words.begin(), words.end()); words.erase(end_unique, words.end()); // sort words by size, but maintain alphabetic order for words of the same size stable_sort(words.begin(), words.end(), isShorter); vector < string > ::size_type wc = count_if(words.begin(), words.end(), GT6); cout << wc << " " << make_plural(wc, "word", "s") // later... << " 6 characters or longer" << endl; return 0; } // 11.3 再谈迭代器 ------------------------------------------------------------------------------------------------------------ /* 11.3.1. 插入迭代器 11.3.2. iostream Iterators 11.3.3. Reverse Iterators 11.3.4. const Iterators 11.3.5. 五种迭代器 */ // 11.3.1. 插入迭代器 #include <iostream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { vector<int> ivec(3,100); list<int> ilst(3,42); ilst.insert(ilst.begin(),1); // 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); it=ilst.begin(); while( it!=ilst.end() ) cout << *it++ << ' '; cout << endl; return 0; } // insert #include <iostream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { list < int > ilst, ilst2, ilst3; // empty lists // 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())); list < int > ::iterator it; it=ilst.begin(); while(it != ilst.end()) cout << *it++ << ' '; cout << endl; it=ilst2.begin(); while(it != ilst2.end()) cout << *it++ << ' '; cout << endl; it=ilst3.begin(); while(it != ilst3.end()) cout << *it++ << ' '; cout << endl; return 0; } // 11.3.2. iostream Iterators #include <iostream> #include <sstream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { vector<int> vec; 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++); vector < int > ::iterator it; it = vec.begin(); while(it != vec.end()) cout << *it++ << ' '; cout << endl; return 0; } // in book #include <iostream> #include <sstream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { istream_iterator < int > in_iter(cin); // read ints from cin istream_iterator < int > eof; // istream "end" iterator vector<int> vec(in_iter, eof); // construct vec from an iterator range vector < int > ::iterator it; it = vec.begin(); while(it != vec.end()) cout << *it++ << ' '; cout << endl; return 0; } // 运行貌似不太正常 #include <iostream> #include <sstream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { // 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++; return 0; } #include <iostream> #include <sstream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { istream_iterator < int > cin_it(cin); // reads ints from cin istream_iterator < int > end_of_stream; // end iterator value // initialize vec from the standard input: vector < int > vec(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); return 0; } // 23 109 45 89 6 34 12 90 34 23 56 23 8 89 23 // 11.3.3. Reverse Iterators #include <iostream> #include <sstream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { vector < int > vec; for(vector < int > ::size_type i = 0; i != 10; ++i) vec.push_back(i); // elements are 0,1,2,...9 // 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 // sorts vec in "normal" order sort(vec.begin(), vec.end()); // sorts in reverse: puts smallest element at the end of vec sort(vec.rbegin(), vec.rend()); return 0; } #include <iostream> #include <sstream> #include <string> #include <vector> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { string line("FIRST,MIDDLE,LAST"); // find first element in a comma-separated list string::iterator comma = find(line.begin(), line.end(), ','); cout << string(line.begin(), comma) << endl; // find last element in a comma-separated list string::reverse_iterator rcomma = find(line.rbegin(), line.rend(), ','); // wrong: will generate the word in reverse order cout << string(line.rbegin(), rcomma) << endl; // ok: get a forward iterator and read to end of line cout << string(rcomma.base(), line.end()) << endl; return 0; } // 11.3.4. const Iterators // 11.3.5. 五种迭代器 // 11.4 泛型算法的结构 -------------------------------------------------------------------------------------------------------- // 11.5 容器特有的算法 --------------------------------------------------------------------------------------------------------