CH10 泛型算法
概述
大多数算法都定义在algorithm头文件中。
Note:算法永远不会执行容器操作
泛型算法本身不会执行容器的操作,而是通过迭代器来访问、修改等操作
10.1
题目要求读取数据存入vector,并实现用户可以查找的值出现在vector中的次数,所以可以考虑用户查找文件中某个数出现的次数,所以可以考虑文件操作
int main(int argc, char* argv[])
{
ifstream infile(argv[]);
if (!infile)
cerr << "can not open the file!" << endl;
vector <int> iv;
int num;
while (infile >> num)
iv.push_back(num);
cout << "please enter the number you want to find" << endl;
int val;
cin >> val;
cout << "the count number " << val << " is :" << count(iv.begin(), iv.end(), val) << endl; system("pause");
return ;
}
10.2
同上,只是,程序区别大小写
#include <iostream>
#include <algorithm>
#include <list>
#include <string>
#include <fstream> using namespace std; int main(int argc, char*argv[])
{
ifstream infile(argv[]);
if (!infile)
{
cerr << "can not open the file,please check" << endl;
return -;
}
list<string>sl;
string words;
while (infile >> words)
sl.push_back(words);
string word;
cout << "please enter the word you want to count" << endl;
cin >> word;
cout <<"the number of "<<word<<" is :"<< count(sl.begin(), sl.end(), word) << endl; }
只读算法
对于只读算法,通常最好使用cbegin()和cend(),但是如果用算法返回的迭代器来改变元素的值,就需要使用begin()和end()的结果作为参数
那些只接受一个单一迭代器来表示第二个序列的算法,都家丁第二个序列至少与第一个序列一样长。
10.3
accumulate(iv.begin(),iv.end(),0)
10.4
accumulate()将第三个参数作为求和的起点,序列中的元素的类型与第三个参数类型匹配,这里第三个是int型,所以前两个会被转换为int型。
写容器算法
一些算法从两个序列中读取元素。构成这两个序列的元素可以来自于不同类型的容器。例如,第一个序列可能保存于一个vector,而第二个可能保存于一个list、deque,内置数组或其他容器中。而且,两个序列中元素的类型也不要求严格匹配。
算法不检查写操作
fill_n(vec.begin(), vec.size(), );//将所有元素重置为0
back_insert:接受一个容器的引用,返回一个与该容器绑定的插入迭代器,当通过此迭代器赋值时,赋值运算符会调用push_back将一个具有给定值的元素添加到容器中
vector<int> vec;
auto it = back_insert(vec);//通过它赋值会将元素添加到vector中
*it = ;//vec 中现在有一个元素42
copy算法:向目的位置的迭代器指向的输出序列中元素写入数据,接受三个迭代器,一对输入范围,第三个目的序列其实位置。
//使用copy实现内置数组的拷贝
int a1[] = { ,,,,,,,,, };
int a2[sizeof(a1) / sizeof(*a1)];//a2与a1大小相同
auto ret = copy(a1, begin(), a1.end(), a2);//使用copy将a1内容拷贝给a2,ret指向拷贝到
//a2的尾元素之后的位置
重排容器元素的算法
sort:接受一对迭代器,表示排序的范围, 按字典顺序排序
unique 重排输入范围,使得每个单词只出现一次
插入迭代器
插入迭代器(insert iterator)迭代器适配器,接受一个容器,生成一个迭代器,该迭代器使用容器操作箱给定容器添加元素。有3个创建插入迭代器的模板:
back_inserter:在类型为T的容器末尾添加元素,创建一个使用push_back的迭代器
front_inserter :容器头部插入元素,创建一个使用push_front的迭代器
inserter:创建一个insert的迭代器,该函数接受两个参数,第二个参数是一个指向容器的迭代器,元素被插入到给定迭代器表示的元素之前
当调用inserter(c,iter)时,c是绑定的容器,得到一个迭代器,使用它时,会将元素插入到iter原来所指向的元素之前的位置。如果it是由inserter生成的迭代器,则下面的语句
*it = val;
效果与下面代码一样
it = c.insert(it, val);
++it;
front_inserter生成的迭代器的行为与inserter生成迭代器不同,front_inserter总是插入到容器的第一个元素之前。
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator> using namespace std; int main()
{
vector<int> iv1 = { ,,,, };
vector<int>iv2;
vector<int>iv3;
vector<int> iv4 = { , };
copy(iv1.cbegin(), iv1.cend(), back_inserter(iv2));
for (auto it : iv2)
cout << it << " ";
cout << endl;
copy(iv1.cbegin(), iv1.cend(), inserter(iv4, iv4.begin()));
for (auto it : iv4)
cout << it << " ";
cout << endl; copy(iv1.cbegin(), iv1.cend(), inserter(iv3, iv3.begin()));
for (auto it : iv3)
cout << it << " ";
cout << endl;
list<int> il1 = { ,,,, };
list<int>il2;
list<int>il3;
copy(il1.cbegin(), il1.cend(), front_inserter(il2));
for (auto it : il2)
cout << it << " ";
cout << endl;
copy(il1.cbegin(), il1.cend(), inserter(il3, il3.begin()));
for (auto it : il3)
cout << it << " ";
cout << endl;
system("pause");
return ;
}
iostream 迭代器
iostream类型不是容器,标准库定义了可用于这些IO类型对象的迭代器
istream_iterator :读取输入流,
ostream_iterator: 想一个输出流写数据
创建一个流迭代器时,必须指定迭代器将要读写的数据的类型。一个istream_iterator使用>>读取流,所以istream_iterator要读取的数据类型必须定义了输入运算符>>.
istream_iterator<int> int_it(cin);//从cin读取int
istream_iterator<int> int_eof;//默认初始化迭代器,初始化为尾后迭代器
ifstream infile("a_file");
istream_iterator<string> str_it(infile);//使用istream_iterator从a_file读取数据
下面是一个使用istream_iterator从cin读取数据存入vector 的例子
istream_iterator<int> in_iter(cin);
istream_iterator<int>eof;
vector<int>vec;
while (in_iter != eof)
vec.push_back(*in_iter++);
测试结果
使用迭代器范围更为简洁
vector<int>vec(in_iter, eof);
测试结果
使用算法操作流迭代器
使用一对istream_iterator 调用accumulate:
istream_iterator<int> in_iter(cin);
istream_iterator<int>eof;
cout << accumulate(in_iter, eof, ) << endl;
此调用会计算从标准输入读取的值的和。
ostream_iterator操作
可以对任何具有输出运算符<<的类型定义ostream_iterator。当创建一个ostream_iterator时,可以提供第二个参数。
ostream_iterator<T>out(os);//out将类型为T的值写到输出流os中
ostream_iterator<T>out(os, d);//out将类型为T的值写到输出流os中,每个值后面都输出一个d,d指向一个
//空字符串结尾的字符数组
使用ostream_iterator输出序列
ostream_iterator<int> out_iter(cout, " ");
for (auto e : vec)
*out_iter++ = e;//赋值语句将元素写入到cout
cout << endl;
当向out_iter赋值时,可以忽略解引用和递增运算,即,循环可以写成下面这样
for (auto e : vec)
out_iter = e;//赋值语句将元素写入到cout
cout << endl;
但是推荐第一种形式,流迭代器的使用和其它迭代器的使用保持一致
//调用copy打印,比循环更简洁
copy(vec.begin(), vec.end(), out_iter);
cout << endl;
10.29
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <fstream>
using namespace std; int main(int argc, char*argv[])
{
ifstream infile(argv[]);
if (!infile)
{
cerr << "can not open the file" << endl;
return -;
}
istream_iterator<string>str_in_iter(infile);//从输入文件流infile读取数据
istream_iterator<string>eof;
vector<string>svec(str_in_iter, eof);
ostream_iterator<string>str_out_iter(cout, " ");
for (auto e : svec)
*str_out_iter++ = e; cout << endl; system("pause");
return ;
}
测试结果
10.30 10.31
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <iterator> using namespace std; int main()
{
istream_iterator<int> in_it(cin);
istream_iterator<int> eof;
vector<int>iv;
while (in_it != eof)
iv.push_back(*in_it++);
sort(iv.begin(), iv.end()); ostream_iterator<int>out_it(cout, " ");
copy(iv.begin(), iv.end(), out_it);
cout << endl;
//10.31
unique_copy(iv.begin(), iv.end(), out_it);
system("pause");
return ;
}
10.33
#include <iostream>
#include <iterator>
#include <fstream> using namespace std; int main(int argc, char*argv[])
{
if (argc != )
cerr << " the number of files is not correct" << endl;
ifstream infile(argv[]);
if (!infile)
{
cerr << "can not open the file " << endl;
return -;
} ofstream odd_out(argv[]);
if (!odd_out)
cerr << "can not open the file or the file does not exist" << endl;
ofstream even_out(argv[]);
if(!even_out)
cerr << "can not open the file or the file does not exist" << endl; istream_iterator<int> in_iter(infile);
istream_iterator<int> eof;
/*ostream_iterator<int>out_iter_odd(cout, " ");
ostream_iterator<int>out_iter_even(cout, " ");*/
ostream_iterator<int>out_iter_odd(odd_out, " ");
ostream_iterator<int>out_iter_even(even_out, " ");
while (in_iter != eof)
{
if (*in_iter % )
*out_iter_odd++ = *in_iter;
else
out_iter_even++ = *in_iter;
in_iter++;
} system("pause");
return ;
}
CH10 泛型算法的更多相关文章
- C++ 泛型算法
<C++ Primer 4th>读书笔记 标准容器(the standard container)定义了很少的操作.标准库并没有为每种容器类型都定义实现这些操作的成员函数,而是定义了一组泛 ...
- C++的那些事:容器和泛型算法
一.顺序容器 1,标准库定义了3种类型的顺序容器:vector.list和deque.它们的差别主要在于访问元素的方式,以及添加或删除元素相关操作运算代价.标准库还提供了三种容器适配器:stack.q ...
- C++ Primer : 第十章 : 泛型算法 之 只读、写和排序算法
大多数算法都定义在<algorithm>头文件里,而标准库还在头文件<numeric>里定义了一组数值泛型算法,比如accumulate. ● find算法,算法接受一对迭代 ...
- Chapter10:泛型算法
泛型算法的基础是迭代器. 迭代器令算法不依赖于容器,但是算法依赖于元素类型的操作.也即:算法永远不会执行容器的操作. 那么,如果想向容器中添加元素或者执行其他的一些操作呢?标准库提供了插入迭代器来完成 ...
- 【STL】帮你复习STL泛型算法 一
STL泛型算法 #include <iostream> #include <vector> #include <algorithm> #include <it ...
- C++ Primer 5th 第10章 泛型算法
练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受一对迭代器和一个值作为参数.count返回给定值在序列中出现的次数.编写程序,读取int序列存入vector ...
- C++标准库之泛型算法
本文中算法都是指泛型算法. 基本要点: 1)算法使用迭代器进行操作. 2)不依赖容器,但容器希望使用算法,就必须提供接口. 3)通用算法永远不会执行容器操作.操作仅指:更改容器大小的操作.但,容器内部 ...
- C++ Primer 读书笔记:第11章 泛型算法
第11章 泛型算法 1.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...
- STL的一些泛型算法
源地址:http://blog.csdn.net/byijie/article/details/8142859 从福州大学资料里摘下来的我现在能理解的泛型算法 algorithm min(a,b) 返 ...
随机推荐
- ThinkPHP3.2.2的函数扩展
ThinkPHP的函数扩展:为了更好的在前台模板中显示变量,例如,商品分类中,分类名称之间的缩进.此时,在APP/Common/Common文件夹下(APP为新建的应用目录),新建一个php文件,如: ...
- 使刚编辑的vim编辑器配置文件立即生效(实为自动生效)
简单的说,在虚拟机下安装的Centos6.3系统后,默认的是没有vim编辑器的配置文件,此时如果有必要,可以按照自己的习惯定制或配置自己的vim编辑器: 1,如果你是root权限,进入root目录下: ...
- Jquery练习1
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 转载--centos7.4安装docker
参考博文:https://www.cnblogs.com/yufeng218/p/8370670.html 作者:风止雨歇 Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企 ...
- uniGUI学习汇总
UniGUI之UniLabel(31) uniGUI之自定义JS事件动作ClientEvents(30) uniGUI之文件下载(29) uniGUI之FDQuery(28) uniGUI之UniPo ...
- python 静态方法,类方法,类下面的函数区别
@clssmenthod(类方法) 与 @staticmethod(静态方法) 与类下面的函数的区别: 1.@classmethod修饰的方法def name(cls)需要通过cls参数传递当前类本身 ...
- tf.reduce_max 与 reduce 系列 API
reduce 可以理解为 python 里的 reduce 函数: tensorflow 中有很多 reduce_ API,其用法完全相同 tf.reduce_max 以这个为例进行说明 def re ...
- CentOS使用日常
安装Teamview TeamViewer官网 下载rpm包 yum install -y teamviewer.x86_64.rpm 搞定 systemctl status firewalld #查 ...
- 服务器settings
1,如果增加了一个新的APP, 那么需要在服务器上 vim settings文件进行修改, 修改方法 i, :wq 2,正式服务器需要一样的操作
- eclipse 快速隐藏所有方法的代码块
java开发中往往一个class文件中会有很多方法,一个方法的实现代码有时候特别长 我个人就喜欢把无关的方法代码全部隐藏起来,只打开当前需要编辑的代码就行了(不喜欢看导航视图,容易头晕) Ctrl+s ...