【 声明:版权所有,转载请标明出处,请勿用于商业用途。 联系信箱:[email protected]】
10.1 概述
1.大多数算法都定义在头文件algorithm中。标准库还在文件numeric中定义了一组数值泛型算法。
10.2 初识泛型算法
1.
accumulate:定义在头文件numeric中。作用是对范围求和。
euqal:定义在头文件algorithm中。作用是判断给定两个区间是否相等。
fill:定义在头文件algorithm中。作用是对给定区间全部赋予某值。
fill_n:定义在头文件algorithm中。作用是对给定迭代器后的n个元素赋予某值。
back_inserter:定义在头文件iterator中。得到指向容器尾部的迭代器。
sort:定义在头文件algorithm中。对指定区间排序。
unique:定义在头文件algorithm中。“消除”重复项,返回指向不重复值范围末尾的迭代器。
erase:定义在头文件algorithm中。删除指定范围内的元素。
10.3 定制操作
1.谓词是一个可调用的表达式,其返回结果是一个能用作条件的值。谓词分为:一元谓词和二元谓词。几元谓词接受几元参数。
2.可调用对象定义;对于一个对象或一个表达式,如果可以对其使用调用运算符,则称为可调用的;可调用的对象有:函数、函数指针、重载函数调用运算符的类和lambda表达式。
lambda表达式形式:
[capture list](parameter list)->return type{function body};
capture list是一个lambda所在函数中定义的局部变量的列表(通常为空);
return type、parameter list和function body分别表示返回类型、参数列表和函数体。
3.标准库bind函数
头文件:functional ;它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表。
调用bind的形式:
auto newCallable=bind(callable, arg_list);
newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。arg_list中的参数可能包含形如_n的名字,_1是newCallable的第一个参数,_2为第二个参数,依次类推。
4.bind拷贝参数而不能拷贝ostream。我们可以使用ref函数。
函数ref返回一个对象,包含给定引用,此对象是可以拷贝的。标准库中海油一个cref函数,生成一个保存const引用的类。与bind一样,函数ref和cref也定义在头文件functional 中。
10.4 再探迭代器
1.
插入迭代器:这些迭代器被绑定到一个容器上,可用来向容器插入元素。
流迭代器:这些迭代器被绑定到输入或输出流上,可用来遍历所有关联的IO流。
反向迭代器:这些迭代器向后而不是向前移动。除了forward_list之外的标准库容器都有反向迭代器。
移动迭代器:这些专用的迭代器不是拷贝其中的元素,而是移动它们。
2.
back_inserter 创建一个使用push_back的迭代器
front_inserter 创建一个使用push_front的迭代器
inserter 创建一个使用insert的迭代器。此函数接受第二个参数,这个参数必须是一个指向给定容器的
迭代器。元素将插入到给定迭代器所表示的元素之前。
3.
istream_iterator操作
istream_iterator
istream_iterator
in1 == in2 in1和in2必须读取相同类型。如果它们都是尾后迭代器,或绑定到相同
in1 != in2 的输入,则两者相等
*in 返回从流中读取的值
in->mem 与(*in).mem的含义相同
++in,in++ 使用元素类型所定义的>>运算符从输入流中读取下一值。与以往一样,前置版本返回一个指向递增后迭代器的引用,后置版本返回旧值
4.
ostream_iterator操作
ostream_iterator
ostream_iterator
out = val; 用<<运算符将val写入到out所绑定的ostream中。val的类型必须与out可写的类型兼容。
*out,++out,out++; 这些运算符是存在的,但不对out做任何事情。每个运算符都返回out
10.5 泛型算法结构
1.迭代器类别
输入迭代器 只读,不写;单遍扫描,只能递增
输出迭代器 只写,不读;单遍扫描,只能递增
前向迭代器 可读写,多遍扫描,只能递增
双向迭代器 可读写,多遍扫描,可递增递减
随机访问迭代器 可读写,多遍扫描,支持全部迭代器运算
10.6 特定容器算法
1.
list和forward_list成员函数版本的算法
lst.merga(lst2)
lst.megra(lst2,comp) 将来自lst2的元素合并入lst。lst和lst2都必须是有序的。元素将从lst2中删除。在合并之后,lst2变成空。第一个版本使用<运算符;第二个版本使用给定的比较操作。
lst.remove(val)
lst.remove_if(pred) 调用erase删除掉与给定值相等(==)或令一元谓词为真的每个元素
lst.reverse() 反转lst中元素的顺序
lst.sort()
lst.sort(comp) 使用<或给定比较操作排序元素
lst.unique()
lst.unique(pred) 调用erase删除统一个值的连续拷贝。第一个版本使用==;第二个版本使用给定的二元谓词
2.
list和forward_list的splice成员函数的参数
lst.splice(args)或flst.splice_after(args)
(p,lst2) p是一个指向lst中元素的迭代器,或一个指向flst首前位置的迭代器。函数将lst2的所有元素移动到lst中p之前的位置或是flst中p之后的位置。将元素从lst2中删除。lst2的类型必须与lst或flst相同,且不能是同一个链表。
(p,lst2,p2) p2是一个指向lst2中位置的有效迭代器。将p2指向的元素移动到lst中,或将p2之后的元素移动到flst中。lst2可以是与lst或flst相同的链表。
(p,lst2,b,e) b和e必须表示lst2中的合法范围。将给定范围中的元素从lst2移动到lst或flst。lst2与lst(或flst)可以是相同的链表,但p不能指向给定范围中元素。
PS:部分练习答案
练习10.1 & 10.2
#include
#include
#include
#include
#include
int main()
{
std::vector vec = {1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,5};
std::cout << "ex 10.1: " << std::count(vec.cbegin(),vec.cend(),5) << "times" << std::endl;
std::list lst = {"a","aa","aa","aa"};
std::cout << "ex 10.2: " << std::count(lst.cbegin(),lst.cend(),"aa") << "times" << std::endl;
return 0;
}
练习10.3 & 10.4
#include
#include
#include
#include
#include
int main()
{
std::vector ivec = {1,2,3,4,5};
std::cout << "ex 10.3: " << std::accumulate(ivec.cbegin(),ivec.cend(),0) << std::endl;
std::vector dvec = {1.1,2.2,3.3,4.4,5.5};
std::cout << "ex 10.4: " << std::accumulate(dvec.cbegin(),dvec.cend(),0) << std::endl;
std::cout << "ex 10.4: " << std::accumulate(dvec.cbegin(),dvec.cend(),double(0)) << std::endl;
return 0;
}
#include
#include
#include
#include
int main()
{
std::vector roster1{"one","two","three"};
std::list roster2{"one","two","three","four","five"};
std::cout << std::equal(roster1.cbegin(),roster1.cend(),roster2.cbegin()) << std::endl;
}
#include
#include
#include
int main()
{
std::vector ivec {1,2,3,4,5,6,7,8,9,10};
std::fill_n(ivec.begin(),ivec.size(),0);
for(auto i: ivec)
std::cout << i << " ";
std::cout << std::endl;
}
a.运行错误,改正为
vector vec;
list lst;
int i;
while (cin >> i) lst.push_back(i);
vec.resize(lst.size());
copy(lst.cbegin(), lst.cend(), vec.begin());
练习10.9
#include
#include
#include
#include
template auto println(Sequence const& seq) -> std::ostream&
{
for(auto const& elem : seq)
std::cout << elem << " ";
return std::cout << std::endl;
}
auto elimDups(std::vector& vs) -> std::vector&
{
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 vs {"a", "v", "a", "s", "v", "a", "a"};
println(vs);
println(elimDups(vs));
return 0;
}
练习10.11
#include
#include
#include
#include
#include
#include
template inline std::ostream& println(Sequence const& seq)
{
for(auto const& elem : seq)
std::cout << elem << " ";
return std::cout;
}
inline bool is_shorter(std::string const& lhs,std::string const& rhs)
{
return lhs.size() < rhs.size();
}
void elimDups(std::vector& 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 vec {"1234", "1234", "1234", "Hi", "alan", "wang"};
elimDups(vec);
std::stable_sort(vec.begin(),vec.end(),is_shorter);
std::cout << "ex 10.11 :" << std::endl;
println(vec);
return 0;
}
练习10.12
#include
#include
#include
#include
#include
#include "ex7_26.h"
inline bool compareIsbn(const Sales_data& d1,const Sales_data& d2)
{
return d1.isbn() vec {d1,d2,d3,d4,d5};
std::sort(vec.begin(),vec.end(),compareIsbn);
for(const auto& elem : vec)
std::cout << elem.isbn() << " ";
std::cout << std::endl;
return 0;
}
练习10.13
#include
#include
#include
#include
bool predicate(const std::string& s)
{
return s.size()>=5;
}
int main()
{
auto vec = std::vector{"a","aaaa","aasaa","bbbbbbb","ccc"};
auto pivot = std::partition(vec.begin(),vec.end(),predicate);
for(auto it = vec.begin();it!=pivot;++it)
std::cout << *it << " ";
std::cout << std::endl;
return 0;
}
练习10.14
auto add = [](int lhs,int rhs){return lhs+rhs;};
练习10.15
int a = 10;
auto add = [a](int b){return a+b;};
练习10.16
#include
#include
#include
#include
void elimDups(std::vector& vec)
{
sort(vec.begin(),vec.end());
auto new_end = std::unique(vec.begin(),vec.end());
vec.erase(new_end,vec.end());
}
void biggies(std::vector vec,std::size_t sz)
{
using std::string;
elimDups(vec);
std::stable_sort(vec.begin(),vec.end(),[](string const& lhs,string const& rhs){return lhs.size()=sz;});
std::for_each(wc,vec.end(),[](const string& s){std::cout << s << " ";});
std::cout << std::endl;
}
int main()
{
std::vector vec {"1234", "1234", "1234", "hi~", "alan", "alan", "cp"};
biggies(vec,3);
std::cout << std::endl;
return 0;
}
#include
#include
#include
#include
#include
#include "ex7_26.h"
int main()
{
Sales_data d1("aa"),d2("aaaa"),d3("aaa"),d4("z"),d5("aaaaz");
std::vector vec {d1,d2,d3,d4,d5};
std::sort(vec.begin(),vec.end(),[](const Sales_data& d1,const Sales_data& d2){return d1.isbn()
#include
#include
#include
#include
//from ex 10.9
void elimdups(std::vector& vs)
{
std::sort(vs.begin(), vs.end());
auto new_end = std::unique(vs.begin(), vs.end());
vs.erase(new_end, vs.end());
}
//ex10.18
void biggies_partition(std::vector& 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.19
void biggies_stable_partition(std::vector& 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 v {"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"};
std::cout << "ex10.18: ";
std::vector v1(v);
biggies_partition(v1, 4);
std::cout << std::endl;
//ex10.19
std::cout << "ex10.19: ";
std::vector v2(v);
biggies_stable_partition(v2, 4);
std::cout << std::endl;
return 0;
}
#include
#include
#include
#include
std::size_t bigerThan6(std::vector vec)
{
return count_if(vec.begin(),vec.end(),[](std::string const& s){return s.size()>6;});
}
int main()
{
std::vector vec{"alan", "moophy", "1234567", "1234567", "1234567", "1234567"};
std::cout << bigerThan6(vec) << std::endl;
}
#include
#include
#include
#include
int main()
{
int i = 7;
auto fun = [&i]()
{
return --i?false:true;
};
while(!fun())
std::cout << i << " ";
std::cout << std::endl;
}
#include
#include
#include
#include
#include
using namespace std::placeholders;
bool isBigerThan6(std::string& s,std::size_t sz)
{
return s.size()>6;
}
int main()
{
std::vector vec {"alan", "moophy", "1234567", "1234567", "1234567", "1234567"};
std::cout << count_if(vec.begin(),vec.end(),bind(isBigerThan6,_1,6)) << std::endl;
}
#include
#include
#include
#include
#include
using namespace std::placeholders;
inline bool check_size(const std::string& s,std::string::size_type sz)
{
return s.size()::const_iterator find_first_bigger(const std::vector& vec,const std::string& s)
{
return find_if(vec.cbegin(),vec.cend(),bind(check_size,s,_1));
}
int main()
{
std::vector vec{1,2,3,4,5,6,7};
std::string s("test");
std::cout << *find_first_bigger(vec,s) << std::endl;
return 0;
}
#include
#include
#include
#include
#include
using namespace std::placeholders;
using std::vector;
using std::string;
void elimDups(vector& vs)
{
sort(vs.begin(),vs.end());
vs.erase(unique(vs.begin(),vs.end()));
}
bool check_size(const string& s,string::size_type sz)
{
return s.size()>=sz;
}
void biggies(vector& words,vector::size_type sz)
{
elimDups(words);
auto iter = std::stable_partition(words.begin(),words.end(),bind(check_size,_1,sz));
for_each(words.begin(),iter,[](const string&s){std::cout< vec{"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"};
biggies(vec,4);
return 0;
}
#include
#include
#include
#include
int main()
{
std::vector vec{1,1,2,2,2,3,3,3,4,5};
std::list lst;
std::unique_copy(vec.begin(),vec.end(),back_inserter(lst));
for(auto elem : lst)
std::cout << elem << " ";
std::cout << std::endl;
}
#include
#include
#include
#include
template void print(Sequence const& seq)
{
for(const auto& elem : seq)
std::cout << elem << " ";
std::cout << std::endl;
}
int main()
{
std::vector vec{1,2,3,4,5,6,7,8,9};
std::list lst1,lst2,lst3;
std::unique_copy(vec.cbegin(),vec.cend(),inserter(lst1,lst1.begin()));
print(lst1);
std::unique_copy(vec.cbegin(),vec.cend(),back_inserter(lst2));
print(lst2);
std::unique_copy(vec.cbegin(),vec.cend(),front_inserter(lst3));
print(lst3);
}
#include
#include
#include
#include
#include
#include
using std::string;
int main()
{
std::ifstream ifs("data.txt");
std::istream_iterator in(ifs),eof;
std::vector vec;
std::copy(in,eof,back_inserter(vec));
std::copy(vec.cbegin(),vec.cend(),std::ostream_iterator(std::cout,"\n"));
return 0;
}
#include
#include
#include
#include
int main()
{
std::istream_iterator in_iter(std::cin),eof;
std::vector vec;
while(in_iter!=eof)
vec.push_back(*in_iter++);
std::sort(vec.begin(),vec.end());
std::copy(vec.cbegin(),vec.cend(),std::ostream_iterator(std::cout," "));
}
#include
#include
#include
#include
int main()
{
std::istream_iterator in_iter(std::cin),eof;
std::vector vec;
while(in_iter!=eof)
vec.push_back(*in_iter++);
std::sort(vec.begin(),vec.end());
std::unique_copy(vec.cbegin(),vec.cend(),std::ostream_iterator(std::cout," "));
}
#include
#include
#include
#include
#include
#include "Sales_item.h"
int main()
{
std::istream_iterator in_iter(std::cin),in_eof;
std::vector vec;
while(in_iter!=in_eof)
vec.push_back(*in_iter++);
sort(vec.begin(),vec.end(),[](Sales_item const& lhs,Sales_item const& rhs){return lhs.isbn()isbn();});
std::cout << std::accumulate(beg,end,Sales_item(beg->isbn())) << std::endl;
}
}
#include
#include
#include
int main(int argc, char** argv)
{
if (argc != 4) return -1;
std::ifstream ifs(argv[1]);
std::ofstream ofs_odd(argv[2]), ofs_even(argv[3]);
std::istream_iterator in(ifs), in_eof;
std::ostream_iterator out_odd(ofs_odd, " "), out_even(ofs_even, "\n");
std::for_each(in, in_eof, [&out_odd, &out_even](const int i)
{
*(i & 0x1 ? out_odd : out_even)++ = i;
});
return 0;
}
#include
#include
#include
#include
#include
#include
//ex 10.34
inline void r_print(const std::vector& v)
{
std::for_each(v.crbegin(), v.crend(),
[](const std::string& s) { std::cout << s << " "; });
}
//! ex 10.35
inline void r_withOrdinary_print(const std::vector& v)
{
for (auto it = std::prev(v.cend()); it != std::prev(v.cbegin()); --it)
std::cout << *it << " ";
}
//ex 10.36
inline std::list::iterator find_last_0(std::list& l)
{
auto r_it = std::find(l.rbegin(), l.rend(), 0);
auto it = r_it.base();
return std::prev(it);
}
//ex 10.37:
inline void vec2list_3_7_reverse(const std::vector& v, std::list& l)
{
std::copy(v.crbegin() + 3, v.crbegin() + 8, std::back_inserter(l));
}
int main()
{
std::vector v = {"aa", "bb", "cc"};
//test for 10.34
r_print(v);
std::cout << "\n";
//test for 10.35
r_withOrdinary_print(v);
std::cout << "\n";
//test for 10.36
std::list l = {1, 2, 3, 4, 0, 5, 6};
auto it = find_last_0(l);
std::cout << *it << "\n";
//test for 10.37
std::vector vi = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::list lst;
vec2list_3_7_reverse(vi, lst);
for (auto e : lst) std::cout << e << " ";
std::cout << std::endl;
return 0;
}
#include
#include
#include
using std::string;
using std::list;
void elimDups(list& words)
{
words.sort();
words.unique();
}
int main()
{
list l = {"aa", "aa", "aa", "aa", "aasss", "aa"};
elimDups(l);
for (const auto& e : l)
std::cout << e << " ";
std::cout << std::endl;
}