大多数算法定义在algorithm中。标准库还在头文件numeric中定义了一组数值泛型算法
练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受一对迭代器和一个值作为参数。count返回给定值在序列中出现的次数。编写程序,读取int序列存入vector中,打印有多少个元素的值等于给定值,
#include
#include
#include
using namespace std;
int main()
{
vector nums = {123,456,789,123,456,789,1};
cout << count(nums.cbegin(), nums.cend(), 123) << endl;
return 0;
}
练习10.3:用accumulate求一个vector
#include
#include
#include
using namespace std;
int main()
{
vector nums = {1,2,3,4,5,6};
cout << accumulate(nums.cbegin(), nums.cend(), 0);
return 0;
}
练习10.9:实现你自己的elimDups。测试你的程序,分别在读取输入后、调用unique后以及调用erase后打印vector的内容。
void elimDups(vector & words)
{
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
}
练习10.11:编写程序,使用stable_sort和isShorter将传递给你的elimDups版本的vector排序。打印vector的内容,验证你程序的正确性
#include
#include
#include
using namespace std;
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
void elimDups(vector & words);
int main()
{
vector words = {"the", "quick", "red", "fox", "jumps", "over",
"the", "slow", "red", "turtle"};
elimDups(words);
stable_sort(words.begin(), words.end(), isShorter);
for (auto i : words)
cout << i << " ";
return 0;
}
void elimDups(vector & words)
{
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
}
练习10.13:标准库定义了名为partition的算法,它接受一个谓词,对容器内容进行划分,使得谓词为true的值会排在容器的前半部分,而未日次false的值会在后半部分。算法返回一个迭代器指向最后一个使谓词位true的元素之后的位置。编写一个函数,接受string,返回bool,指出string是否有5个或更多字符。使用此函数划分words打印长度大于等于5的元素,
#include
#include
#include
#include
using namespace std;
bool compareWords(const string &);
int main()
{
vector words = {"the", "quick", "red", "fox", "jumps", "over",
"the", "slow", "red", "turtle"};
auto end = partition(words.begin(), words.end(), compareWords);
for (auto i = words.begin(); i != end; ++i)
{
cout << *i << " ";
}
return 0;
}
bool compareWords(const string & words)
{
return words.size() > 4;
}
lambda
lambda表达式形式:
[capture list] (parameter list) -> return type { function body}
- 捕获列表只用于局部非静态变量。
- 可以直接使用局部静态变量和外部变量
练习10.14:编写一个lambda,接受两个int,返回他们的和。
#include
using namespace std;
int main()
{
int a = 5, b = 4;
auto f = [](const int a, const int b) {return a + b;};
cout << f(a, b) << endl;
}
练习10.15:编写一个lambda,捕获它所在函数的int,并接受一个int参数。lambda应该返回捕获的int和int参数的和。
#include
using namespace std;
int main()
{
int a = 5, b = 4;
auto f = [a](const int b) {return a + b;};
cout << f(b) << endl;
}
从写biggies用partition代替find_if
void biggies(vector &words, vector::size_type sz)
{
elimDups(words);
stable_sort(words.begin(), words.end(),
[](const string &a, const string &b)
{ return a.size() < b.size();});
auto wz = partition(words.begin(), words.end(),
[sz](string &a)
{ return a.size() < sz;});
for_each( wz, words.end(),
[](const string &a)
{cout << a << " ";});
cout << endl;
}
在创建lambda的时候捕获列表就保存了捕获的值
修改捕获列表的值必须使用mutable
auto f = [&a] () mutable {return ++a;};
返回其他类型使用尾置返回类型
可以使用bind代替lambda
引用 ref bind(print, ref(os), _1, ' ')
placeholders命名空间
using namespace std::placeholders;
练习10.22:重写统计长度小于等于5的单词数量的程序。使用函数代替lambda;
#include
#include
#include
#include
#include
using namespace std;
using namespace std::placeholders;
void biggies(vector &words, vector::size_type sz);
void elimDups(vector &words);
bool check6(const string &a, string::size_type sz); //bind
int main()
{
vector words = {"the", "quick", "red", "fox", "jumps", "over",
"the", "slow", "red", "turtle"};
biggies(words, 5);
}
void elimDups(vector &words)
{
sort(words.begin(), words.end());
auto no_unique = unique(words.begin(), words.end());
words.erase(no_unique, words.end());
}
void biggies(vector &words, vector::size_type sz)
{
elimDups(words);
stable_sort(words.begin(), words.end(),
[](const string &a, const string &b)
{ return a.size() < b.size();});
auto wz = find_if(words.begin(), words.end(),
bind(check6, _1, sz));
for_each(words.begin(), wz,
[](const string &a)
{cout << a << " ";});
cout << endl;
}
bool check6(const string &a, string::size_type sz)
{
return a.size() > sz;
}
练习10.23:bind接受几个参数?
auto newCallable = bind(callable, arg_list);
练习10.26:解释三种插入迭代器的不同之处
- back_inserter:创建使用push_back的迭代器
- front_inserter创建一个使用push_front的迭代器
- inserter:创建一个使用insert的迭代器。此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。
练习10.27:使用unique_copy函数将不重复的字母copy到一个初始化为空的list中
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
vector words = {"the", "quick", "red", "fox", "jumps", "over",
"the", "slow", "red", "turtle"};
list wwww;
sort(words.begin(), words.end());
unique_copy(words.cbegin(), words.cend(), inserter(wwww, wwww.begin()));
for (auto i : words)
cout << i << " ";
cout << endl;
for (auto i : wwww)
cout << i << " ";
cout << endl;
return 0;
}
练习10.28:一个vector中保存1-9用三种迭代器copy到三种不同的容器
练习10.29:编写程序,使用流迭代器读取一个文本文件,存入一个vector中的string里
#include
#include
#include
#include
#include
using namespace std;
int main()
{
ifstream in("1.txt");
istream_iterator str_it(in);
istream_iterator eof;
vector str(str_it, eof);
ostream_iterator out_iter(cout, " ");
copy(str.cbegin(), str.cend(), out_iter);
cout << endl;
return 0;
}
练习10.30:使用流迭代器、sort和copy从标准输入读取一个整数序列,将其排序,并将结构写到标准输出
#include
#include
#include
#include
#include
using namespace std;
int main()
{
istream_iterator in_iter(cin);
istream_iterator eof;
vector nums(in_iter, eof);
sort(nums.begin(), nums.end());
ostream_iterator out_iter(cout, " ");
copy(nums.cbegin(), nums.cend(), out_iter);
return 0;
}
练习10.34:使用reverse_iterator逆序打印一个vector
#include
#include
#include
#include
using namespace std;
int main()
{
vector vec = {1,2,3,4,5,6,7,8};
for (auto r_iter = vec.crbegin();
r_iter != vec.crend();
++r_iter)
cout << *r_iter << endl;
return 0;
}
练习10.37:给定一个包含10个元素的vector,将3-7之间的元素逆序拷贝到list中
#include
#include
#include
using namespace std;
int main()
{
vector num = {1,2,3,4,5,6,7,8,9,0};
list nums(num.crbegin() + 3, num.crend() - 2);
for (auto i : nums)
cout << i << " ";
cout << endl;
return 0;
}
练习10.38:列出5个迭代器类别,以及每类迭代器所支持的操作。
输入迭代器:只读,不写;单遍扫描,只能递增
输出迭代器:只写,不读:单遍扫描,只能递增
前向迭代器:可读写;多遍扫描,只能递增
双向迭代器:可读写;多遍扫描,可递增递减
随机访问迭代器:可读写,多遍扫描,支持全部迭代器运算