zoukankan      html  css  js  c++  java
  • CH10 泛型算法

    概述

    大多数算法都定义在algorithm头文件中。

    Note:算法永远不会执行容器操作

    泛型算法本身不会执行容器的操作,而是通过迭代器来访问、修改等操作

    10.1

    题目要求读取数据存入vector,并实现用户可以查找的值出现在vector中的次数,所以可以考虑用户查找文件中某个数出现的次数,所以可以考虑文件操作

     1 int main(int argc, char* argv[])
     2 {
     3     ifstream infile(argv[1]);
     4     if (!infile)
     5         cerr << "can not open the file!" << endl;
     6     vector <int> iv;
     7     int num;
     8     while (infile >> num)
     9         iv.push_back(num);
    10     cout << "please enter the number you want to find" << endl;
    11     int val;
    12     cin >> val;
    13     cout << "the count number " << val << " is :" << count(iv.begin(), iv.end(), val) << endl;
    14     
    15     system("pause");
    16     return 0;
    17 }

    10.2

    同上,只是,程序区别大小写

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <list>
     4 #include <string>
     5 #include <fstream>
     6 
     7 using namespace std;
     8 
     9 int main(int argc, char*argv[])
    10 {
    11     ifstream infile(argv[1]);
    12     if (!infile)
    13     {
    14         cerr << "can not open the file,please check" << endl;
    15         return -1;
    16     }
    17     list<string>sl;
    18     string words;
    19     while (infile >> words)
    20         sl.push_back(words);
    21     string word;
    22     cout << "please enter the word you want to count" << endl;
    23     cin >> word;
    24     cout <<"the number of  "<<word<<" is :"<< count(sl.begin(), sl.end(), word) << endl;
    25 
    26 }

    只读算法

    对于只读算法,通常最好使用cbegin()和cend(),但是如果用算法返回的迭代器来改变元素的值,就需要使用begin()和end()的结果作为参数

    那些只接受一个单一迭代器来表示第二个序列的算法,都家丁第二个序列至少与第一个序列一样长。

     10.3

    accumulate(iv.begin(),iv.end(),0)

    10.4

    accumulate()将第三个参数作为求和的起点,序列中的元素的类型与第三个参数类型匹配,这里第三个是int型,所以前两个会被转换为int型。

    写容器算法

    一些算法从两个序列中读取元素。构成这两个序列的元素可以来自于不同类型的容器。例如,第一个序列可能保存于一个vector,而第二个可能保存于一个list、deque,内置数组或其他容器中。而且,两个序列中元素的类型也不要求严格匹配。

    算法不检查写操作

    1 fill_n(vec.begin(), vec.size(), 0);//将所有元素重置为0

    back_insert:接受一个容器的引用,返回一个与该容器绑定的插入迭代器,当通过此迭代器赋值时,赋值运算符会调用push_back将一个具有给定值的元素添加到容器中

    1 vector<int> vec;
    2     auto it = back_insert(vec);//通过它赋值会将元素添加到vector中
    3     *it = 42;//vec 中现在有一个元素42

    copy算法:向目的位置的迭代器指向的输出序列中元素写入数据,接受三个迭代器,一对输入范围,第三个目的序列其实位置。

    1 //使用copy实现内置数组的拷贝
    2     int a1[] = { 0,1,2,3,4,5,6,7,8,9 };
    3     int a2[sizeof(a1) / sizeof(*a1)];//a2与a1大小相同
    4     auto ret = copy(a1, begin(), a1.end(), a2);//使用copy将a1内容拷贝给a2,ret指向拷贝到
    5     //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总是插入到容器的第一个元素之前。

     1 #include <iostream>
     2 #include <vector>
     3 #include <list>
     4 #include <algorithm>
     5 #include <iterator>
     6 
     7 using namespace std;
     8 
     9 int main()
    10 {
    11     vector<int> iv1 = { 1,2,3,4,5 };
    12     vector<int>iv2;
    13     vector<int>iv3;
    14     vector<int> iv4 = { 6,7 };
    15     copy(iv1.cbegin(), iv1.cend(), back_inserter(iv2));
    16     for (auto it : iv2)
    17         cout << it << " ";
    18     cout << endl;
    19     copy(iv1.cbegin(), iv1.cend(), inserter(iv4, iv4.begin()));
    20     for (auto it : iv4)
    21         cout << it << " ";
    22     cout << endl;
    23 
    24     copy(iv1.cbegin(), iv1.cend(), inserter(iv3, iv3.begin()));
    25     for (auto it : iv3)
    26         cout << it << " ";
    27     cout << endl;
    28     list<int> il1 = { 1,2,3,4,5 };
    29     list<int>il2;
    30     list<int>il3;
    31     copy(il1.cbegin(), il1.cend(), front_inserter(il2));
    32     for (auto it : il2)
    33         cout << it << " ";
    34     cout << endl;
    35     copy(il1.cbegin(), il1.cend(), inserter(il3, il3.begin()));
    36     for (auto it : il3)
    37         cout << it << " ";
    38     cout << endl;
    39     system("pause");
    40     return 0;
    41 }

     

    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 的例子

    1 istream_iterator<int> in_iter(cin);
    2     istream_iterator<int>eof;
    3     vector<int>vec;
    4     while (in_iter != eof)
    5         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, 0) << 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

     1 #include <iostream>
     2 #include <vector>
     3 #include <string>
     4 #include <iterator>
     5 #include <fstream>
     6 using namespace std;
     7 
     8 int main(int argc, char*argv[])
     9 {
    10     ifstream infile(argv[1]);
    11     if (!infile)
    12     {
    13         cerr << "can not open the file" << endl;
    14         return -1;
    15     }
    16     istream_iterator<string>str_in_iter(infile);//从输入文件流infile读取数据
    17     istream_iterator<string>eof;
    18     vector<string>svec(str_in_iter, eof);
    19     ostream_iterator<string>str_out_iter(cout, " ");
    20     for (auto e : svec)
    21         *str_out_iter++ = e;
    22 
    23     cout << endl;
    24 
    25     system("pause");
    26     return 0;
    27 }

    测试结果

     10.30 10.31

     1 #include <iostream>
     2 #include <vector>
     3 #include <fstream>
     4 #include <algorithm>
     5 #include <iterator>
     6 
     7 using namespace std;
     8 
     9 int main()
    10 {
    11     istream_iterator<int> in_it(cin);
    12     istream_iterator<int> eof;
    13     vector<int>iv;
    14     while (in_it != eof)
    15         iv.push_back(*in_it++);
    16     sort(iv.begin(), iv.end());
    17 
    18     ostream_iterator<int>out_it(cout, " ");
    19     copy(iv.begin(), iv.end(), out_it);
    20     cout << endl;
    21     //10.31
    22     unique_copy(iv.begin(), iv.end(), out_it);
    23     system("pause");
    24     return 0;
    25 }

    10.33

     1 #include <iostream>
     2 #include <iterator>
     3 #include <fstream>
     4 
     5 using namespace std;
     6 
     7 
     8 int main(int argc, char*argv[])
     9 {
    10     if (argc != 4)
    11         cerr << " the number of files is not correct" << endl;
    12     ifstream infile(argv[1]);
    13     if (!infile)
    14     {
    15         cerr << "can not open the file " << endl;
    16         return -1;
    17     }
    18 
    19     ofstream odd_out(argv[2]);
    20     if (!odd_out)
    21         cerr << "can not open the file or the file does not exist" << endl;
    22     ofstream even_out(argv[3]);
    23     if(!even_out)
    24        cerr << "can not open the file or the file does not exist" << endl;
    25 
    26     istream_iterator<int> in_iter(infile);
    27     istream_iterator<int> eof;
    28     /*ostream_iterator<int>out_iter_odd(cout, " ");
    29     ostream_iterator<int>out_iter_even(cout, " ");*/
    30     ostream_iterator<int>out_iter_odd(odd_out, " ");
    31     ostream_iterator<int>out_iter_even(even_out, " ");
    32     while (in_iter != eof)
    33     {
    34         if (*in_iter % 2)
    35             *out_iter_odd++ = *in_iter;
    36         else
    37             out_iter_even++ = *in_iter;
    38         in_iter++;
    39     }
    40 
    41     system("pause");
    42     return 0;
    43 }
  • 相关阅读:
    问题S
    为什么说程序员的前三年不要太看重工资水平
    Oracle查看锁表与解锁方法
    .net 动态代理的泛型方法支持问题
    探索Windows Azure 监控和自动伸缩系列3
    探索Windows Azure 监控和自动伸缩系列2
    探索Windows Azure 监控和自动伸缩系列1
    如何找到w3wp与w3svc的对应关系
    妙用perfmon Alert抓dump
    .net RPC框架选型(一)
  • 原文地址:https://www.cnblogs.com/Holly-blog/p/7414178.html
Copyright © 2011-2022 走看看