c++ primer第10章 - 泛型算法

1 概述

    标准库没有给每个容器提供大量的功能,而是提供了一组算法,这些算法大部分独立于特定的容器。这些算法是通用的:他们可以用于不同类型的容器和不同类型的元素。

    泛型算法:一些经典算法的公共接口,用于不同类型元素、多种容器类型的排序、搜索。

头文件:algorithm

    这些算法一般,遍历由两个迭代器指定的一个元素范围来操作:

               auto result = find(vec.cbegin(),vec.cend(),42);

算法不会影响容器的大小,不会删除、添加元素,及算法不能执行容器操作;

2 初识泛型算法

2.1 accumulate()求和:

计算两个迭代器之间元素的和,第三个参数是初始值;定义的“+”运算的类型,都可以使用accumulate函数;

//算术求和

vector <int> venc;

int sum = accumulate(venc.cbedin(),venc.cend(),0);


//连接字符串

vector <string> v;

string sum = accumulate<v.cbegin(),v.cend(),string(" ") );

2.2 equal() 求等长类型相等否

equal(roster1.cbegin(), roster1.cend(),roster2.cbegin() );

roster1.cbegin(), roster1.cend(): 表示一个序列;

roster2.cbegin():第二个序列的首元素;


注意:

1 两个序列类型可以不一样,只要能用 == 比较就行;

2 算法假设两个序列一样长,在第二个序列中取出相同长度和一序列比较;

2.3 fill() 、fill_n()写容器

fill(venc.begin(),venc.end(),0 ); //将迭代器范围的值设为0;

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

fill_n(dest.begin(), n ,val)  //dest的前n个重置为cal;


2.4 copy()拷贝算法


2.5 replace()替换序列某元素

replace(ilst.begin(),ilst.end(),0,42);   //将所有的 0 改为 42;

2.6 replace_copy()拷贝替换


2.7 sort()排序


sort(word.begin(),word.end()):范围内从小到大排序;

unique(word.begin(),word.end()):一般用于sort排序后的序列,将重复的元素排在后面,返回第一个重复元素所在位置;


sort(histVector.begin(), histVector.end(), greater<float>());

上述例子中系统自己为sort提供了less仿函数。在STL中还提供了其他仿函数,以下是仿函数列表:

名称

功能描述

equal_to

相等

not_equal_to

不相等

less

小于

greater

大于

less_equal

小于等于

greater_equal

大于等于





3 定制操作 

标准库,允许我们提供资金定义的操作;如sort()的方向排序;

3.1 向算法传递函数

sort的重载版本有第三个参数,其是谓词(只接受一个或者两个参数)


按照长度从短到长排序words

sort(words.begin(),words.end(),isShorter);

stable_wort(words.begin(),words.end(),isShorter);  //长度从短到长,相等大小的,按字母表顺序排;


elimDup(words);  //将words按字典排序,删除重复单词;

 //用partition()函数,第三个谓词参数为真的排在前面,为假的排在后面,返回第一个为假的

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

//! Predicate
inline
bool isLongerThan5(const std::string &s)
{
    return s.size() >= 5;
}

void partition_words(std::vector<std::string> &v)
{
    auto iter_longerLast = std::partition(v.begin(), v.end(), isLongerThan5);

    //! @note   the range to be printed not whole of the v, so can't use for range.
    for(auto it = v.begin(); it != iter_longerLast; ++it)
        std::cout << *it << " ";
    std::cout << std::endl;
}

int main()
{
    std::vector<std::string> v{"a","as","aasss","aaaaassaa","aaaaaabba","aaa"};
    partition_words(v);

    return 0;
}

3.2 lambda 表达式

可调用对象有:函数、指针、重载了函数调用运算符的类、lambda表达式;

lambda表达式,表示一个可调用的代码单元。

    与任何函数类似,一个lambda具有一个返回类型、一个参数列表、一个函数体;

    lambda可能定义在函数内部;


  1. [captures] (params) -> ret {Statments;}  


    注释:[capturne]方括号中的数是另外包含进去的可使用的数;

        

//sort()排序、enique()再排序、vs.erase()删除重复、stable_sort()大小字幕表排序、find_if()找到第一个大小为3的、for_each打印每个大于等于三的;

    auto wc = std::find_if(vs.begin(), vs.end(),[sz](string const& s){
            return s.size() >= sz;
    });
 std::for_each(wc, vs.end(), [](const string &s){
        std::cout << s << " ";
    }); 

//找出vector<strig> 中,所有size()大于3的字符串,并输出,不可重复;

//

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

//! from ex 10.9
void elimdups(std::vector<std::string> &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<std::string> &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<std::string> &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<std::string> v{
        "the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"
    };
    
    std::cout << "ex10.18: ";
    std::vector<std::string> v1(v);
    biggies_partition(v1,4);
    std::cout << std::endl;

    //! ex10.19
    std::cout << "ex10.19: ";
    std::vector<std::string> v2(v);
    biggies_stable_partition(v2,4);
    std::cout << std::endl;

    return 0;
}

3.3 lambda值捕获:


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


using std::vector;
using std::count_if;
using std::string;


//! Exercise 10.20
std::size_t bigerThan6(vector<string> const& v)
{
    return count_if(v.cbegin(), v.cend(), [](string const& s){
        return s.size() > 6;
    });
}


int main()
{
    //! ex10.20
    vector<string> v{
        "alan","moophy","1234567","1234567","1234567","1234567"
    };
    std::cout << "ex10.20: " << bigerThan6(v) << std::endl;

    //! ex10.21
    int i = 7;
    auto check_and_decrement = [&i](){ return --i ? false : true; };
    std::cout << "ex10.21: ";
    while(!check_and_decrement())
        std::cout << i << " ";
    std::cout << i << std::endl;

    return 0;
}


//! output  :
//!
//ex10.20: 4
//ex10.21: 6 5 4 3 2 1 0


3.4 参数绑定


//统计长度大于等于6的个数

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using std::string;
using namespace std::placeholders;

bool isBiggerThan6(const string &s, string::size_type sz)
{
    return s.size() > sz;
}

int main()
{
    std::vector<string> authors{"Mooophy", "pezy", "Queequeg90", "shbling", "evan617"};
    std::cout << count_if(authors.cbegin(), authors.cend(), bind(isBiggerThan6, _1, 6));
}

//  @Out
//  4

4 再探迭代器



4.1 插入迭代器





  std::unique_copy(vec.begin(), vec.end(), back_inserter(lst)); //无重复的拷贝;

4.2 iostream迭代器

4.2.1 istream_iterator迭代器



stream_iterator<int> in_iter(cin); //

stream_iterator<int> eof;  //定义为空,从而可当作尾后迭代器来使用。




4.2.2 ostream_iterator



//读入一个文本,将其存入vector<string>中,并输出
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>

using std::string;

int main()
{
    std::ifstream ifs("../data/book.txt");
    std::istream_iterator<string> in(ifs), eof;
    std::vector<string> vec;
    std::copy(in, eof, back_inserter(vec));
    
    // output
    std::copy(vec.cbegin(), vec.cend(), std::ostream_iterator<string>(std::cout, "\n"));
}

//读入数列,并排序无重复输出
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
    std::istream_iterator<int> in_iter(std::cin), eof;
    std::vector<int> 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<int>(std::cout, " "));
}

4.4 反向迭代器


//寻找并打印第一个单词
auto comma=find(line.begin(),line.end(),',');
cout<<string(line.begin(),comma)<<endl;

//选择并打印最后一个单词
auto rcomma=find(line.rbegin(),line.rend(),',');
cout<<string(rcomma.base(),line.end());

//将v的3到7之间的数,逆序拷贝到I中;
 std::copy(v.crbegin() + 3, v.crbegin() + 8, std::back_inserter(l));

5 泛型算法结果



6 特定容器算法








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值