Chapter 10. Generic Algorithms
来源:互联网 发布:魔兽7..0mac版插件 编辑:程序博客网 时间:2024/06/03 13:53
练习10.7: 下面的程序是否有错误?如果有,请改正。
(a)
vector<int>vec;list<int>lst;int i;while (cin >> i)lst.push_back(i);copy(lst.cbegin(),lst.cend(), vec.begin());
(b)
vector<int>v;v.reserve(10);fill_n(v.begin(), 10, 0);(a)Fixed: added this statement :vec.resize(lst.size());
vector<int>vec;list<int>lst;int i;while (cin >> i)lst.push_back(i);vec.resize(lst.size());copy(lst.cbegin(), lst.cend(), vec.begin());
Cause Algorithms that write to a destination iterator assume the destination is large enough to hold the number of elements being written.
Another way to fix bug :
copy(lst.cbegin(), lst.cend(), back_inserter(vec));
(b)Fixed: 1. use v.resize(10);
or 2. use fill_n(std::back_inserter(v), 10, 0);
vector<int>v;v.resize(10);fill_n(v.begin(), 10, 0);
c.reserve(n);分配至少能容纳n个元素的内存空间。
vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector的capacity同时也增加了它的size!
原因如下:
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。
resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的
只读算法:
#include<numeric>// sum the elements in vec starting the summation with the value 0int sum = accumulate(vec.cbegin(), vec.cend(), 0);
string sum = accumulate(v.cbegin(), v.cend(), string(""));
Best Practices
Ordinarily it is best to usecbegin()andcend() with algorithms that read, but do not write, the elements.
Another read-only algorithm is equal, which lets us determine whether two sequences hold the same values.
// roster2 should have at least as many elements as roster1equal(roster1.cbegin(), roster1.cend(), roster2.cbegin());
Algorithms That Write Container Elements写容器元素的算法
fill(vec.begin(), vec.end(), 0); // reset each element to 0// set a subsequence of the container to 10fill(vec.begin(), vec.begin() + vec.size()/2, 10);back_inserter定义在头文件iterator中
vector<int> vec; // empty vectorauto it = back_inserter(vec); // assigning through it adds elements to vec*it = 42; // vec now has one element with value 42
vector<int> vec; // empty vector // ok: back_inserter creates an insert iterator that adds elements to vecfill_n(back_inserter(vec), 10, 0); // appends ten elements to vecCopy Algorithms拷贝算法
int a1[] = { 0,1,2,3,4,5,6,7,8,9 };int a2[sizeof(a1) / sizeof(*a1)]; // a2 has the same size as a1 // ret points just past the last element copied into a2auto ret = copy(begin(a1), end(a1), a2); // copy a1 into a2
// replace any element with the value 0 with 42replace(ilst.begin(), ilst.end(), 0, 42);This call replaces all instances of 0 by 42
// use back_inserter to grow destination as neededreplace_copy(ilst.cbegin(), ilst.cend(),back_inserter(ivec), 0, 42);After this call, ilst is unchanged, and iveccontains a copy ofilst with the
exception that every element in ilst with the value 0 has the value 42 inivec.
练习10.9:
#include <iostream>#include <string>#include <vector>#include <algorithm>// print containers like vector,deque, list, etc.template <typename Sequence> auto println(Sequence const& seq) -> std::ostream &{for (auto const& elem : seq) std::cout << elem << " ";return std::cout << std::endl;}auto eliminate_duplicates(std::vector<std::string>& vs)-> std::vector<std::string> &{std::sort(vs.begin(), vs.end());println(vs);auto new_end = std::unique(vs.begin(), vs.end());println(vs);vs.erase(new_end, vs.end());return vs;}int main(){std::vector<std::string> vs{ "a", "v", "a", "s", "v", "a", "a" };println(vs);println(eliminate_duplicates(vs));system("pause");return 0;}运行结果:
练习10.11:编写程序,使用stable_sort和is_shorter将传递给你的elimdups版本的vector排序。
#include <iostream>#include <string>#include <vector>#include <algorithm>#include <numeric>#include <list>template<typename Sequence>inline std::ostream& println(Sequence const &seq){for (auto const& elem : seq)std::cout << elem << " ";std::cout << std::endl;return std::cout;}inline bool is_shorter(std::string const&lhs, std::string const& rhs){return lhs.size() < rhs.size();}void elimdups(std::vector<std::string>&vs){std::sort(vs.begin(), vs.end());auto new_end = std::unique(vs.begin(), vs.end());vs.erase(new_end, vs.end());}int main(){std::vector<std::string>v = { "abc","acb","bac","bca","cab","cba","abc","acb","123","123","1234","1234","Hi" };std::cout << "原始输入:"; println(v); std::cout << std::endl;elimdups(v);std::cout << "排序并去除相同元素:"; std::cout << std::endl;println(v); std::cout << std::endl; std::stable_sort(v.begin(), v.end(),is_shorter);//stable_sort保持等长元素的字典序std::cout << "加入等长元素排序(练习10.11):"; std::cout << std::endl;println(v); std::cout << std::endl;system("pause");return 0;}运行结果:
练习10.13:
#include <iostream>#include <string>#include <vector>#include <algorithm>bool predicate(const std::string& s){return s.size() >= 5;}int main(){auto v = std::vector<std::string>{ "a","as","aasss","aaaaassaa","aaaaaabba","aaa" };auto pivot = std::partition(v.begin(), v.end(), predicate);//接受一个谓词,true在前,false在后,返回最后一个true元素之后的位置for (auto it = v.cbegin(); it != pivot; ++it) std::cout << *it << " ";std::cout << std::endl;system("pause");return 0;}
练习10.16:
#include <iostream>#include <string>#include <vector>#include <algorithm>void elimdups(std::vector<std::string>&vs){std::sort(vs.begin(), vs.end());auto new_end = std::unique(vs.begin(), vs.end());vs.erase(new_end, vs.end());}void biggies(std::vector<std::string>&vs, std::size_t sz){using std::string;elimdups(vs); //sort by size,but maintain alphabetical order for same size.std::stable_sort(vs.begin(), vs.end(), [](string const & lhs, string const &rhs) {return lhs.size() < rhs.size(); });//get an iterator to the first one whose size() is >=szauto wc = std::find_if(vs.begin(), vs.end(), [sz](string const &s) {return s.size() >= sz; });//print the biggiesstd::for_each(wc, vs.end(), [](const string&s) {std::cout << s << " "; });}int main(){std::vector<std::string> v{ "1234", "1234", "1234", "hi~","alan", "alan", "cp","a","adfdsgfsdgf" };std::cout << " Ex 10.16:";biggies(v, 3);std::cout << std::endl;system("pause");return 0;}
关于std::for_each的用法示例:
#include <vector>#include <algorithm>#include <iostream> struct Sum { Sum() { sum = 0; } void operator()(int n) { sum += n; } int sum;}; int main(){ std::vector<int> nums{3, 4, 2, 9, 15, 267}; std::cout << "before: "; for (auto n : nums) { std::cout << n << " "; } std::cout << '\n'; std::for_each(nums.begin(), nums.end(), [](int &n){ n++; }); Sum s = std::for_each(nums.begin(), nums.end(), Sum()); std::cout << "after: "; for (auto n : nums) { std::cout << n << " "; } std::cout << '\n'; std::cout << "sum: " << s.sum << '\n';}输出:
before: 3 4 2 9 15 267
after: 4 5 3 10 16 268
sum: 306
练习10.18/10.19:
#include <iostream>#include <string>#include <vector>#include <algorithm>//! from ex 10.9void elimdups(std::vector<std::string>& vs){ std::sort(vs.begin(), vs.end()); auto new_end = std::unique(vs.begin(), vs.end()); vs.erase(new_end, vs.end());}//! ex10.18void biggies_partition(std::vector<std::string>& vs, std::size_t sz){ elimdups(vs); auto pivot = partition(vs.begin(), vs.end(), [sz](const std::string& s) { return s.size() >= sz; }); for (auto it = vs.cbegin(); it != pivot; ++it) std::cout << *it << " ";}//! ex10.19void biggies_stable_partition(std::vector<std::string>& vs, std::size_t sz){ elimdups(vs); auto pivot = stable_partition(vs.begin(), vs.end(), [sz](const std::string& s) { return s.size() >= sz; }); for (auto it = vs.cbegin(); it != pivot; ++it) std::cout << *it << " ";}int main(){ //! ex10.18 std::vector<std::string> v{"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"}; std::cout << "ex10.18: "; std::vector<std::string> v1(v); biggies_partition(v1, 4); std::cout << std::endl; //! ex10.19 std::cout << "ex10.19: "; std::vector<std::string> v2(v); biggies_stable_partition(v2, 4); std::cout << std::endl; return 0;}//! output ://!// ex10.18: turtle jumps over quick slow// ex10.19: jumps over quick slow turtle
值捕获:
void fcn1(){size_t v1 = 42;//局部变量auto f = [v1] {return v1;};//将V1拷贝到名为f的可调用对象v1 = 0;auto j = f();//j为42;f保存了我们创建它时v1的拷贝}
引用捕获:
void fcn2(){size_t v1 = 42;//局部变量auto f2 = [&v1] {return v1;};//对象f2包含v1的引用v1 = 0;auto j = f2();//j为0;f2保存v1的引用,而非拷贝}
Warning!当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的。一般来说,我们应该尽量减少捕获的数据量,来避免潜在的捕获导致的问题。而且,如果可能的话,应该避免捕获指针或引用。
可变lambda
void fcn3(){size_t v1 = 42;//局部变量auto f = [v1]()mutable {return ++v1; };//f可以改变它所捕获的变量的值v1 = 0;auto j = f();//j为43}void fcn4(){size_t v1 = 42;//局部变量,v1是一个非const变量的引用auto f2 = [&v1] {return ++v1; };//可以通过f2中的引用来改变它v1 = 0;auto j = f2();//j为1}
#include <iostream>#include <string>#include <cctype>#include <vector>#include <algorithm>int main(){std::vector<int>vi{ 1,2,3,-1,-2,-3,4,5,6,-4,-5,-6 };transform(vi.begin(), vi.end(), vi.begin(), [](int i) {return i < 0 ? -i : i; });for (auto ele : vi)std::cout << ele << " ";std::cout<<std::endl;std::string s("hello,luwenwen!");std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))std::toupper);std::cout << s;std::cout << std::endl;system("pause");return 0;}
使用尾置返回类型:
transform(vi.begin(), vi.end(), vi.begin(), [](int i)->int {if (i < 0)return-i; else return i; });
#include <algorithm>#include <iostream>#include <string>#include <vector>using std::vector;using std::string;using std::cout;using std::endl;int main(){vector<string> words{ "cppprimer", "pezy", "learncpp","greater", "rewrite", "programmer" };cout << std::count_if(words.cbegin(), words.cend(), [](const string& word) {return word.size() > 6;}) << std::endl;system("pause");}
练习10.21:
#include <iostream>using std::cout;using std::endl;int main(){int local_val = 7;// local int variableauto decrement_to_zero = [&local_val]() {if (local_val == 0)return true;else {--local_val;return false;}};while (!decrement_to_zero()) cout << local_val << ",";system("pause");}运行结果:
- Chapter 10. Generic Algorithms
- Chapter 10. Generic Algorithms
- !!!Chapter 11 Generic Algorithms
- chapter 22 Elementary Graph Algorithms
- Chapter 9 Templates. Generic Programming. and STL
- C++ Chapter 7. Templates and Generic Programming
- Chapter 16 Templates and Generic Programming
- !!!Chapter 16 Templates and Generic Programming
- C++ Primer Chapter 11 generic algorithm
- Chapter 7Iterators and the Generic for
- Chapter.16 Templates And Generic Programming
- Algorithms ——chapter 0 Prologue 序言
- 《C++ Primer第五版》读书笔记(8)--GENERIC ALGORITHMS
- Cortex ™ -M0 Devices Generic User Guide(Chapter 1)
- Chapter 1 The Role of Algorithms in Computing
- Introduction to Algorithms (算法导论) 学习笔记 -- Chapter 9
- Introduction to Algorithms Chapter 12: Binary Search Tree
- Introduction to Algorithms Chapter 13: Red Black Tree
- 苹果iOS11正式版更新内容大全:史上变动最大
- 补间动画和属性动画的用法
- Windows10图片查看设置器
- 30张java基础思维导图,梳理知识点和思路
- 使用二维高斯函数模糊图片
- Chapter 10. Generic Algorithms
- spring boot restful API风格
- 史上最全的MySQL(zip安装)
- 写给阿蒙的浏览器插件安装使用指南
- 如何在Fragment中监听触摸事件
- SpringBoot学习笔记之打包部署
- SpringMVC Controller介绍及常用注解
- Node.js模块全局安装路径配置
- 蝉道Bug管理工具的环境搭建