练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受一对迭代器和一个值作为参数。count返回给定值在序列中出现的次数。编写程序,读取int序列存入vector中,打印有多少个元素的值等于给定值。

#include <iostream>
#include <algorithm>
#include <vector> int main()
{
std::vector<int> v = {, , , , , , , , , }; std::cout << count(v.begin(), v.end(), ) << std::endl;
return ;
}

练习10.2:重做上一题,但读取string序列存入 list 中。

#include <iostream>
#include <algorithm>
#include <list> int main()
{
std::list<std::string> v = {"af", "fe", "fea", "ers", "ht", "tq", "bs", "et"};
std::cout << count(v.begin(), v.end(), "ab") << std::endl; return ;
}

练习10.3:用accumulate求一个vector<int>中的元素之和。

#include <iostream>
#include <algorithm> int main()
{
std::vector<int> v = {, , , , , , , , , };
std::cout << std::accumulate(v.begin(), v.end(), ) << std::endl; return ;
}

练习10.4:假定v是一个vector<double>,那么调用 accumulate(v.cbegin(),v.cend(),0) 有何错误(如果存在的话)?

由于类型不同,隐式转换时会导致丢失精度,最终结果与实际结果有偏差。

练习10.5:在本节对名册(roster)调用equal 的例子中,如果两个名册中保存的都是C风格字符串而不是string,会发生什么?

练习10.6:编写程序,使用fill_n将一个序列中的 int 值都设置为 0。

#include <iostream>
#include <algorithm> int main()
{
std::vector<int> v = {, , , , , , , , , };
fill_n(v.begin(), v.size(), );
return ;
}

练习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> vec;
vec.reserve();
fill_n(vec.begin(), , );

(a)vec是空vector,不可以使用copy
(b)vec也是空vector,虽然底层内存上是正确的,但逻辑上错误。

练习10.8:本节提到过,标准库算法不会改变它们所操作的容器的大小。为什么使用back_inserter不会使这一断言失效?

因为back_inserter不属于标准库泛型算法,它是在头文件iterator中定义的,而泛型算法是在algorithm中定义的。

练习10.9:实现你自己的elimDups。测试你的程序,分别在读取输入后、调用 unique后以及调用erase后打印vector的内容。

#include <iostream>
#include <algorithm> using std::cout;
using std::endl; void eliminate_duplicates(std::vector<std::string> &v)
{
std::sort(v.begin(), v.end());
for (auto i : v)
{
cout << i << " ";
}
cout << endl; auto end_unique = std::unique(v.begin(), v.end());
for (auto i : v)
{
cout << i << " ";
}
cout << endl; v.erase(end_unique, v.end());
for (auto i : v)
{
cout << i << " ";
}
cout << endl; } int main()
{
std::vector<std::string> v = {"abc", "abc", "efg", "hij", "klmn", "opq", "xyz", "klmn"};
eliminate_duplicates(v);
return ;
}

练习10.10:你认为算法不改变容器大小的原因是什么?

算法不改变容器将使用户不需要顾忌容器的迭代器失效问题。

练习10.11:编写程序,使用stable_sort和isShorter将传递给你的elimDups版本的vector排序。打印vector的内容,验证你的程序的正确性。

#include <iostream>
#include <vector>
#include <algorithm> //using namespace std; void elimDups(std::vector<std::string>& words)
{
std::sort(words.begin(), words.end());
auto unique_end = unique(words.begin(), words.end());
words.erase(unique_end, words.end());
} bool isShorter(const std::string& i1, const std::string& i2)
{
return i1.size() < i2.size();
} int main()
{
std::vector<std::string> word = {"", "", "", "", "", "", "", "", "", ""};
elimDups(word);
stable_sort(word.begin(), word.end(), isShorter);
for (auto one : word)
{
std::cout << one << '\t';
}
std::cout << std::endl;
return ;
}

练习10.12:遍写名为compareIsbn的函数,比较两个 Sales_data 对象的isbn( ) 成员。使用这个函数排序一个保存 Sales_data 对象的 vector。

bool compareIsbn(const Sales_data &sd1, const Sales_data &sd2)
{
return sd1.isbn().size() < sd2.isbn().size();
} std::sort(v.begin(), v.end(), compareIsbn);

练习10.13:标准库定义了名为 partition 的算法,它接受一个谓词,对容器内容进行划分,使得谓词为true 的值会排在容器的前半部分,而使得谓词为 false 的值会排在后半部分。算法返回一个迭代器,指向最后一个使谓词为 true 的元素之后的位置。编写函数,接受一个 string,返回一个 bool 值,指出 string 是否有5个或更多字符。使用此函数划分 words。打印出长度大于等于5的元素。

#include <iostream>
#include <vector>
#include <algorithm> //using namespace std; bool morethan5(const std::string& s)
{
return s.size() < ;
} int main()
{
std::vector<std::string> words = {"hello", "one", "two", "three", "seven", "eleven"};
partition(words.begin(), words.end(), morethan5);
for (auto one : words)
{
std::cout << one << ' ';
}
std::cout << std::endl;
return ;
}

练习10.14:编写一个 lambda ,接受两个int,返回它们的和。

#include <iostream>

int main(int argc, char const *argv[])
{
auto f = [](int i, int j) {return i + j;};
std::cout << f(, ) << std::endl;
return ;
}

练习10.15:编写一个 lambda ,捕获它所在函数的 int,并接受一个 int参数。lambda 应该返回捕获的 int 和 int 参数的和。

#include <iostream>

int main(int argc, char const *argv[])
{
int i = ;
auto f = [i](int j) {return i + j;};
std::cout << f() << std::endl;
return ;
}

练习10.16:使用 lambda 编写你自己版本的 biggies。

练习10.17:重写10.3.1节练习10.12(第345页)的程序,在对sort的调用中使用 lambda 来代替函数 compareIsbn。

std::sort(v.begin(), v.end(), [](const Sales_data &sd1, const Sales_data &sd2) 
{
return sd1.isbn().size() < sd2.isbn().size();
});

练习10.18:重写 biggies,用 partition 代替 find_if。我们在10.3.1节练习10.13(第345页)中介绍了 partition 算法。

#include <iostream>
#include <algorithm> void elimDups(std::vector<std::string> &v)
{
std::sort(v.begin(), v.end());
auto end = std::unique(v.begin(), v.end());
v.erase(end, v.end());
} void biggies(std::vector<std::string> &words, std::size_t sz)
{
elimDups(words);
stable_sort(words.begin(), words.end(), [](const std::string & a, const std::string & b) { return a.size() < b.size();});
auto wc = partition(words.begin(), words.end(), [sz](const std::string & s) { return s.size() < sz; });
auto count = words.end() - wc;
std::cout << count << " " << "word(s)"
<< " of length " << sz << " or longer" << std::endl;
for_each(wc, words.end(), [](const std::string & s) {std::cout << s << " ";});
std::cout << std::endl;
} int main()
{
std::vector<std::string> v = {"abc", "abc", "efg", "hij", "klmn", "opq", "xyz", "klmn"};
biggies(v,);
return ;
}

练习10.19:用 stable_partition 重写前一题的程序,与 stable_sort 类似,在划分后的序列中维持原有元素的顺序。

#include <iostream>
#include <vector>
#include <algorithm> void elimDups(std::vector<std::string> &v)
{
std::sort(v.begin(), v.end());
auto end = std::unique(v.begin(), v.end());
v.erase(end, v.end());
} void biggies(std::vector<std::string> &words, std::size_t sz)
{
elimDups(words);
auto wc = stable_partition(words.begin(), words.end(), [sz](const std::string & s) {return s.size() < sz;});
auto count = words.end() - wc;
std::cout << count << " " << "word(s)"
<< " of length " << sz << " or longer" << std::endl;
for_each(wc, words.end(), [](const std::string & s) {std::cout << s << " ";});
std::cout << std::endl;
} int main()
{
std::vector<std::string> v = {"abc", "abc", "efg", "hij", "klmn", "opq", "xyz", "klmn"};
biggies(v, );
return ;
}

练习10.20:标准库定义了一个名为 count_if 的算法。类似 find_if,此函数接受一对迭代器,表示一个输入范围,还接受一个谓词,会对输入范围中每个元素执行。count_if返回一个计数值,表示谓词有多少次为真。使用count_if重写我们程序中统计有多少单词长度超过6的部分。

#include <iostream>
#include <vector>
#include <algorithm> int main()
{
std::vector<std::string> v = {"abc", "hello", "I think", "I am", "alphabet"};
std::cout << count_if(v.begin(), v.end(), [](const std::string & s1) {return s1.size() > ;});
return ;
}

练习10.21:编写一个 lambda,捕获一个局部 int 变量,并递减变量值,直至它变为0。一旦变量变为0,再调用lambda应该不再递减变量。lambda应该返回一个bool值,指出捕获的变量是否为0。

#include <iostream>
#include <vector>
#include <algorithm> int main()
{
int i = ;
auto lambda = [&i] ()mutable -> bool
{ if (i != )
{
for (; i != ; --i)
{
continue;
}
return true;
}
return false; };
lambda();
std::cout << i << std::endl;
return ;
}

练习10.22:重写统计长度小于等于6的单词数量的程序,使用函数代替 lambda。

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm> bool f(const std::string s, std::size_t size)
{
return s.size() <= size;
} int main()
{
std::vector<std::string> v = {"abc", "hello", "I think", "I am", "alphabet"};
std::cout << count_if(v.begin(), v.end(), bind(f, std::placeholders::_1, ));
return ;
}

练习10.23:bind 接受几个参数?

没有限制

练习10.24:给定一个string,使用 bind 和 check_size 在一个 int 的vector 中查找第一个大于string长度的值。

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm> bool check_size(const std::string s, std::size_t size)
{
return s.size() < size;
} int main()
{
std::string s;
std::cin >> s;
std::vector<int> v = {, , , , };
for (auto i : v)
{
auto f = bind(check_size, s, std::placeholders::_1);
if ((f(i)))
{
std::cout << "finded.the element is " << i << std::endl; break;
}
}
return ;
}

练习10.25:在10.3.2节(第349页)的练习中,编写了一个使用partition 的biggies版本。使用 check_size 和 bind 重写此函数。

#include <iostream>
#include <algorithm>
#include <functional> void elimDups(std::vector<std::string> &v)
{
std::sort(v.begin(), v.end());
auto end = std::unique(v.begin(), v.end());
v.erase(end, v.end());
} bool f(const std::string& s, std::size_t sz)
{
return s.size() < sz;
} void biggies(std::vector<std::string> &words, std::size_t sz)
{
elimDups(words);
stable_sort(words.begin(), words.end(), [](const std::string & a, const std::string & b)
{
return a.size() < b.size();
});
auto wc = partition(words.begin(), words.end(), bind(f, std::placeholders::_1, sz) );
auto count = words.end() - wc;
std::cout << count << " " << "word(s)"
<< " of length " << sz << " or longer" << std::endl;
for_each(wc, words.end(), [](const std::string & s) {std::cout << s << " ";});
std::cout << std::endl;
} int main()
{
std::vector<std::string> v = {"abc", "abc", "efg", "hij", "klmn", "opq", "xyz", "klmn"};
biggies(v, );
return ;
}

练习10.26:解释三种插入迭代器的不同之处。

back_inserter尾部插入,要求push_back操作
front_inserter首部插入,要求front_inserter操作
inserter 插入到指定位置

练习10.27:除了 unique(参见10.2.3节,第343页) 之外,标准库还定义了名为 unique_copy 的函数,它接受第三个迭代器,表示拷贝不重复元素的目的位置。编写一个程序,使用 unique_copy将一个vector中不重复的元素拷贝到一个初始化为空的list中。

#include <iostream>
#include <list>
#include <algorithm> int main()
{
std::vector<int> v = {, , , , , , , , , };
std::list<int> lst;
unique_copy(v.begin(), v.end(), back_inserter(lst));
for (auto i : lst)
{
std::cout << i << " ";
}
std::cout << std::endl;
return ;
}

练习10.28:一个vector 中保存 1 到 9,将其拷贝到三个其他容器中。分别使用inserter、back_inserter 和 front_inserter 将元素添加到三个容器中。对每种 inserter,估计输出序列是怎样的,运行程序验证你的估计是否正确。

#include <algorithm>
#include <iostream>
#include <deque>
#include <list> int main()
{
std::vector<int> v = {, , , , , , , , };
std::deque<int> v1, v2, v3;
copy(v.begin(), v.end(), back_inserter(v1));
copy(v.begin(), v.end(), front_inserter(v2));
copy(v.begin(), v.end(), back_inserter(v3));
std::cout << "v1 " << "v2 " << "v3" << std::endl;
for (int i = ; i != ; ++i)
{
std::cout << v1[i] << " " << v2[i] << " " << v3[i] << std::endl;
}
std::cout << std::endl;
return ;
}

练习10.29:编写程序,使用流迭代器读取一个文本文件,存入一个vector中的string里。

#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string> int main()
{
std::ifstream file_in("nmap.txt");
if (file_in)
{
std::istream_iterator<std::string> in_it{file_in};
std::istream_iterator<std::string> in_end;
std::vector<std::string> v;
std::copy(in_it, in_end, back_inserter(v));
for (auto i : v)
{
std::cout << i << " ";
}
}
else
{
std::cout << "file open failed.";
}
std::cout << std::endl;
return ;
}

练习10.30:使用流迭代器、sort 和 copy 从标准输入读取一个整数序列,将其排序,并将结果写到标准输出。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector> int main()
{ std::istream_iterator<int> in_it{std::cin};
std::istream_iterator<int> in_end; std::vector<int> v;
std::copy(in_it, in_end, back_inserter(v));
std::sort(v.begin(), v.end()); std::ostream_iterator<int> out_it{std::cout, " "};
std::copy(v.begin(), v.end(), *out_it++); std::cout << std::endl;
return ;
}

练习10.31:修改前一题的程序,使其只打印不重复的元素。你的程序应该使用 unique_copy(参见10.4.1节,第359页)。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector> int main()
{
std::istream_iterator<int> in_it{std::cin};
std::istream_iterator<int> in_end; std::vector<int> v;
std::copy(in_it, in_end, back_inserter(v));
std::sort(v.begin(), v.end()); std::ostream_iterator<int> out_it{std::cout, " "};
std::unique_copy(v.begin(), v.end(), *out_it++); std::cout << std::endl;
return ;
}

练习10.32:重写1.6节(第21页)中的书店程序,使用一个vector保存交易记录,使用不同算法完成处理。使用 sort 和10.3.1节(第345页)中的 compareIsbn 函数来排序交易记录,然后使用 find 和 accumulate 求和。

练习10.33:编写程序,接受三个参数:一个输入文件和两个输出文件的文件名。输入文件保存的应该是整数。使用 istream_iterator 读取输入文件。使用 ostream_iterator 将奇数写入第一个输入文件,每个值后面都跟一个空格。将偶数写入第二个输出文件,每个值都独占一行。

#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <vector> int main()
{
std::ifstream file_in{"file_in"};
std::ofstream file_out1{"file_out1"}, file_out2{"file_out2"};
if (!file_in || !file_out1 || !file_out2)
{
std::cout << "file open failed." << std::endl;
return -;
}
//in
std::istream_iterator<int> in_it{file_in}, in_end; //out
std::ostream_iterator<int> out_it1{file_out1, " "};
std::ostream_iterator<int> out_it2{file_out2, " "}; while (in_it != in_end)
{
if ((*in_it) % )
{
out_it1 = *in_it;
}
else
{
out_it2 = *in_it;
}
++in_it;
} std::cout << std::endl;
return ;
}

练习10.34:使用 reverse_iterator 逆序打印一个vector。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector> int main()
{
std::vector<int> v = {, , , , };
auto b = v.crbegin(), e = v.crend();
while (b != e )
{
std::cout << *b << ' ';
++b;
}
std::cout << std::endl;
return ;
}

练习10.35:使用普通迭代器逆序打印一个vector。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector> int main()
{
std::vector<int> v = {, , , , };
auto b = v.cbegin(), e = v.cend();
while (b != e )
{
std::cout << *--e << ' ';
}
std::cout << std::endl;
return ;
}

练习10.36:使用 find 在一个 int 的list 中查找最后一个值为0的元素。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <list> int main()
{
std::list<int> l = {, , , , , , };
auto b = l.crbegin(), e = l.crend();
auto result = std::find(b, e, );
std::cout << *b - *result << std::endl; //使用8-0来验证查找到的0是最后一个0
std::cout << std::endl;
return ;
}

练习10.37:给定一个包含10 个元素的vector,将位置3到7之间的元素按逆序拷贝到一个list中。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <list> int main()
{
std::vector<int> v = {, , , , , , , , , };
std::list<int> l;
std::copy(v.crbegin() + , v.crend() - , std::back_inserter(l));
for (auto i : l)
{
std::cout << i << " ";
}
return ;
}

练习10.38:列出5个迭代器类别,以及每类迭代器所支持的操作。

1.输入迭代器
*iterator,++iterator,==,!=,->
2.输出迭代器
*iterator,++iterator
3.前向迭代器
*iterator,++iterator,==,!=,->
4.双向迭代器
*iterator,++iterator,--iterator,==,!=.->
5.随机访问迭代器
*iterator,++iterator,--iterator,==,!=.->,<,>,+=,-,iterator[n]

练习10.39:list 上的迭代器属于哪类?vector呢?

list的迭代器属于双向迭代器
vector的迭代器属于随机访问迭代器

练习10.40:你认为 copy 要求哪类迭代器?reverse 和 unique 呢?

copy要求两个输入和一个输出迭代器
reverse要求双向迭代器
unique要求前向迭代器

练习10.41:仅根据算法和参数的名字,描述下面每个标准库算法执行什么操作:

replace(beg, end, old_val, new_val); //替换beg和end指定范围内所有old_val的值为new_val
replace_if(beg, end, pred, new_val); //替换beg和end指定范围内使得pred为真的所有元素的值为new_val
replace_copy(beg, end, dest, old_val, new_val); //将beg和end指定范围内的所有old_val替换为new_val,并将新的序列写入到dest指定的容器
replace_copy_if(beg, end, dest, pred, new_val); //将beg和end指定范围内使得pred为真的所有元素的值替换为new_val,并将新的序列写入到dest指定的容器

练习10.42:使用 list 代替 vector 重新实现10.2.3节中的去除重复单词的程序。

#include <iostream>
#include <algorithm>
#include <list> void elimDups(std::list<std::string>& words)
{
words.sort(); words.unique();
} int main()
{
std::list<std::string> l = {"", "", "", "", "", "", ""};
elimDups(l);
for (auto i : l)
{
std::cout << i << " ";
}
return ;
}

C++ Primer 5th 第10章 泛型算法的更多相关文章

  1. 【c++ Prime 学习笔记】第10章 泛型算法

    标准库未给容器添加大量功能,而是提供一组独立于容器的泛型算法 算法:它们实现了一些经典算法的公共接口 泛型:它们可用于不同类型的容器和不同类型的元素 利用这些算法可实现容器基本操作很难做到的事,例如查 ...

  2. [C++ Primer] : 第10章: 泛型算法

    概述 泛型算法: 称它们为"算法", 是因为它们实现了一些经典算法的公共接口, 如搜索和排序; 称它们是"泛型的", 是因为它们可以用于不同类型的元素和多种容器 ...

  3. 《C++ Primer》笔记 第10章 泛型算法

    迭代器令算法不依赖于容器,但算法依赖于元素类型的操作. 算法永远不会执行容器的操作.算法永远不会改变底层容器的大小. accumulate定义在头文件numeric中,接受三个参数,前两个指出需要求和 ...

  4. C++ Primer 读书笔记:第11章 泛型算法

    第11章 泛型算法 1.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...

  5. C++ Primer 5th 第2章 变量和基本类型

    *****代码在Debian g++ 5.3.1 / clang++ 3.8(C++11)下编写调试***** 由于部分编译器对标准遵循的不同以及自身额外的扩展,本章书中的少数知识点与实际实现存在偏差 ...

  6. 第十一章 泛型算法 C++ PRIMER

    vector<int>::const_iterator result = find(vector.begin(). vector.end(),search_value); 如果查找失败,分 ...

  7. 【C++ Primer | 10】泛型算法

    #include<iostream> #include<algorithm> #include<vector> #include<string> #in ...

  8. C++ Primer 5th 第1章 开始

    *****代码在Ubuntu g++ 5.31 / clang++ 3.8(C++11)下编写调试***** 每个C++程序必须有一个main( )函数,main( )函数的返回值也必须是int类型, ...

  9. C++ Primer 5th 第12章 动态内存

    练习12.1:在此代码的结尾,b1 和 b2 各包含多少个元素? StrBlob b1; { StrBlob b2 = {"a", "an", "th ...

随机推荐

  1. JButton 做图片框

    JButton setHorizontalTextPosition(SwingConstants.CENTER);// 在水平方向文字位于图片中央 setVerticalTextPosition(Sw ...

  2. Android Studio导入Eclipse项目

    随着Google 对新Android编辑器Android Studio(以下简称AS)的版本不断更新,越来越多的人开始由熟悉的编辑器Eclipse转向AS,而Eclipse开发团队也坦言将放弃对Ecl ...

  3. QTP自传之描述性编程

    描述性编程,即采用描述性的语言定位对象,不需要事先将对象添加到对象库中.下面,就说说如何使用描述性编程,我们将继续使用对象库编程中的网页. 使用描述性编程的两种方法 直接描述 对象("属性名 ...

  4. Subsets —— LeetCode

    Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a subset must ...

  5. [转载]你需要知道的 16 个 Linux 服务器监控命令

    转载自: 你需要知道的 16 个 Linux 服务器监控命令 如果你想知道你的服务器正在做干什么,你就需要了解一些基本的命令,一旦你精通了这些命令,那你就是一个 专业的 Linux 系统管理员. 有些 ...

  6. 也谈BIO | NIO | AIO (Java版--转)

    关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一个解释: BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个 ...

  7. Necklace of Beads

    http://poj.org/problem?id=1286 // File Name: poj1286.cpp // Author: bo_jwolf // Created Time: 2013年1 ...

  8. Windows环境下python多版本配置方案

    系统环境 Windows,安装了msys2,windows和msys2都安装了python,且版本比较多,使用shell/bash聚合工具conemu64 配置方案 配置msys2环境用户目录下的.b ...

  9. 性能比较工具runstats

    runstats能对做同一件事的两个不同方法进行比较,得出谁好一点.我们只需要提供两个不同方法,余下的事情都由runstats负责.runstats只是测量3个要素: 1. 耗用的时间. 2. 系统统 ...

  10. ashx一般处理程序文件用处

    今天逛博客园,无意发现一篇好文章,关于ashx文件的使用. 文章一:向服务器发送josn字符串,服务器端解析 本文转载:http://www.cnblogs.com/yzenet/p/3470388. ...