C++通用算法

文章详细介绍了C++STL中的算法,包括复制、填充、查找、替换、排序和集合操作等,并探讨了函数对象如bind1st、bind2nd、mem_fun、mem_fun_ref等的使用,以及如何自定义函数对象和适配器。此外,还讲解了迭代器的不同类型及其在STL算法中的角色。
摘要由CSDN通过智能技术生成

1.概述

根据名字就知道如何使用相关算法,比如copy函数,就是复制的意思,它需要一个范围,以及要复制的位置

copy(begin, end, container_begin);

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
 
int main(int argc, char** argv) {
vector<int> data(10);//创建一个大小为10的向量 
cout << data.capacity() << endl;
int arr[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
copy(begin(arr), end(arr), data.begin());//copy(起点,终点,容器开头);
for(auto it : data){
cout << it << " ";
} 
cout << endl;
return 0;
}

copy函数需要容器的起点,这样就要求我们提前设定容器的大小,比如上面的代码,设定了容器的大小为10,有时候我们并知道需要copy多少数据,所以

我们可以使用back_inserter(),这个函数返回一个特殊的迭代器,插入的时候,容器会自动扩大,插入到前面数据的后面

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
int main(int argc, char** argv) {
vector<int> data;
int d[] = {1,2,3,4,5,6,7,8,9,10};
copy(begin(d), end(d), back_inserter(data));
for(int i : d){
cout << i << endl;
}
return 0;
}

(1)判定函数

很多算法需要一个返回bool类型的函数,根据函数来自定义算法的工作过程,比如:

remove_copy_if(),除了限定范围,还要指定函数,返回为false的数据会被复制

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
bool compare(int x){
return x > 6;
}
int main(int argc, char** argv) {
vector<int> data;
int d[] = {1,2,3,4,5,6,7,8,9,10};
remove_copy_if(begin(d), end(d), back_inserter(data), compare);//复制小于6的数据 
for(int i : data){
cout << i << endl;
}
return 0;
}

类似的还有replace_copy_if(起点,终点,容器起点,函数,替代数据)

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
bool compare(int x){
return x > 6;
}
int main(int argc, char** argv) {
vector<int> data;
int d[] = {1,2,3,4,5,6,7,8,9,10};
replace_copy_if(begin(d), end(d), back_inserter(data), compare, 10);
for(int i : data){
cout << i << endl;
}
return 0;
}

而replace_if则是改变原始的数据,而不是输出到新的容器

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
bool compare(int x){
return x > 6;
}
int main(int argc, char** argv) {
vector<int> data;
int d[] = {1,2,3,4,5,6,7,8,9,10};
replace_if(begin(d), end(d),compare, 10);
for(int i : d){
cout << i << endl;
}
return 0;
}

(2)流迭代器

流迭代器把数据当作流进行操作

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
bool compare(int x){
    return x > 6;
}
int main(int argc, char** argv) 
{
    vector<int> data;
    int d[] = {1,2,3,4,5,6,7,8,9,10};
    copy(begin(d), end(d), ostream_iterator<int>(cout,"\n"));//直接输出到cout
    return 0;
}

输出流迭代器重载拷贝-复制操作符,该重载操作符向相应的流写入数据,当然我们也可以使用其他的流来操作数据

比如输入流来操作输入数据到某个容器或者相应的流.

2.函数对象

有时候需要根据对象调用函数,以对象名作为函数进行调用,这样做的好处是,对于需要多个参数才能实现的功能,可以通过函数对象实现

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
#include<fstream>
using namespace std;
class MyFunction{
private:
int value;
public:
MyFunction(int i):value(i){}
bool operator()(int x){
return x > value;
}
};
int main(int argc, char** argv){
int arr[] = {1,2,3,4,5,6,7,8,9,10};
vector<int> data;
MyFunction fun(5);//函数对象
remove_copy_if(begin(arr), end(arr), back_inserter(data), fun);//复制小于等于5的数据
for(int i : data){
cout << i << " ";
}
}

2.1自动创建函数对象

头文件<functional>定义了大量的通用的函数对象,其中函数对象适配器可以调整函数对象。

比如greater是一个二元函数对象,也就是有两个参数,当第一个参数大于第二个参数时返回true,从greater重写上面的程序,还不够,需要函数

对象适配器调整参数,这里使用bind2nd,可以调整greater函数的第二个参数

#include <iostream>
#include<vector>
#include<algorithm>
#include<iterator>
#include<fstream>
using namespace std;
int main(int argc, char** argv){
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    vector<int> data;
    remove_copy_if(begin(arr), end(arr), back_inserter(data), bind2nd(greater<int>(),5));
    for(int i : data){
    cout << i << " ";
    }
    return 0;
}

bind2nd创建一个binder2nd函数对象,这个对象储存和传递两个参数给bind2nd,第一个参数是二元函数或者函数对象。这里的函数不能任意定义,必须是

按照一种特殊的形式来定义。

int arr[] = {1,1,1,4,5,6,7,8,9,10};
vector<int> data;
greater<int> g;
auto b = bind2nd(g, 5);
cout << count_if(begin(arr), end(arr), b) << endl;

equal_to是一个标准二元函数对象

not1是一个函数对象适配器,它对一元函数对象的值进行设置

C++提供了许多函数对象,比如加减乘除,取余,大于,小于,不等于,等等

2.2 可调整的函数对象

在前面,我们介绍了函数适配器,用来调整函数对象的值,之所以可以调整,是因为他们使用了一套公用的规则,

比如bind2nd就需要知道函数对象的参数类型和返回类型,使用bind2nd来操作自定义的函数对象,除非自定义的对象使用C++约定的规则,否则无法成功

对于一元函数对象,类型名是argument_type和result_type,

对于二元函数对象,类型名是first_argumen_type和second_argument_type和result_type

bind1st的重载函数定义如下:

typename Op::result_type operator()(const typename Op::second_argument_type& x) const

为这些类提供类型名的函数对象被称为可调整的函数对象

C++提供了两个类来提供这些类型,程序员自定义的函数对象通过继承的方式,可以使用这些类型,这两个类分别是

unary_function和binary_function

unary_function的定义:

template<class arg, class Result>

struct unary_function{

typedef Arg argument_type;

typedef Result result_type;

};

binary_function的定义类似,不过变成了first_argumen_type和second_argument_type和result_type

2.3 函数指针适配器

函数可以通过函数名来调用,但是有很大的局限性。有时候需要函数指针来调用函数,这是可能用到函数指针适配器,它可以把函数指针转化为函数对象

ptr_fun就是函数指针适配器,但是它只能封装一元函数或者二元函数

它的定义如下:

template<class Arg, class Result>

pointer_to_unary_function<Arg, Result>

ptr_fun(Result (*fptr)(Arg){

return pointer_to_unary_function<Arg, Result>(fptr);

}

函数模板可以推测出函数的返回值类型和函数的参数类型,然后返回一个函数对象

而pointer_to_unary_function是一个函数对象,其定义如下:

template<class Arg, class Result>

class pointer_to_unary_function: public unary_function<Arg, Result>{

Result (*fptr)(Arg);//储存函数

public:

pointer_to_unary_function(Result (*x)(Arg) : fptr(x){}

Result operator()(Arg x)const{

return fptr;

}

};

结合上面两份代码可知,ptr_fun通过接受一个函数,推测出函数的类型,然后生成一个pointer_to_unary_function函数对象,调用对象函数

使用这种方法调用函数有一个缺陷,就是可能会产生二义性,比如函数重载了,此刻就需要模板特化

使用例子:

#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
using namespace std; 
int isEven(int a){
    return a % 2 == 0;
}
int main(int argc, char** argv) {
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    vector<int>buf;
    transform(begin(arr), end(arr), back_inserter(buf), ptr_fun(isEven));
    for(int i : buf){
    cout << i << endl;
    }
    return 0;
}

for_each函数:for_each(起点,终点,操作);这个函数把一段序列的对象调用到操作上,这个操作可以自定义。

比如输出一个数组

#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
using namespace std; 
void print(int a){
cout << a << endl;
}
int main(int argc, char** argv)
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    ostream_iterator<int> out(cout, " ");
    for_each(begin(arr), end(arr), print);
    return 0;
}

我们也可以通过这个方法来实现多态,通过mem_fun函数实现

另外还有mem_fun_ref。

他们之间不同点在于,mem_fun需要对象是指针,而mem_fun_ref需要对象是普通对象

#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
using namespace std; 
class Base{
public:
    virtual void print() = 0;
    virtual ~Base(){}
};

class One:virtual public Base{
public:
void print(){
    cout << "One" << endl;
}
};

class Two: virtual public Base{
public:
    void print(){
    cout << "Two" << endl;
    }
};

int main(int argc, char** argv) 
{
    vector<Base*> vs;
    vs.push_back(new One);
    vs.push_back(new Two);
    for_each(begin(vs), end(vs), mem_fun(Base::print));//输出 One Two 
    for(Base* i : vs)
    {
        delete i;
    }
    return 0;
}

下面作为对比

#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
using namespace std; 
class Angle{
    int value;
    public:
    Angle(int v): value(v){}
    void print(){
    cout << value << endl;
    }
};
int main(int argc, char** argv) {
    vector<Angle*> va;
    for(int i = 0; i < 5; i++){
        va.push_back(new Angle(i));
    }
    for_each(begin(va), end(va), mem_fun(Angle::print));//输出 One Two 
    return 0;
}

transform函数,起点到终点的序列,调用第四个参数的函数,保存在第三个参数,这个参数一般是序列的首地址

generate函数,让起点到终点的序列调用第三个参数的函数,并且把结果保存在序列中

2.4 编写自己的函数对象适配器

下面我们写一个程序,自动生成一个字符串序列,然后在主函数中转化为小数


#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
#include<ctime>
#include<cstdlib>
#include<string>
using namespace std; 

//生成一个随机的数字字符串 
class NumStringGen{
    const int sz;
public:
    NumStringGen(int ssz): sz(ssz){}
    
    string operator()(){
        string digits("0123456789");
        const int ndigits = digits.size();
        string r(sz,' ');
        r[0] = digits[rand()% (ndigits - 1)] + 1; 
        for(int i = 0; i < sz; ++i){
            if(sz >= 3 && i == sz/2)
                r[i] = '.';
            else
                r[i] = digits[rand() % ndigits];
        }
        return r;
    }
    
}; 

//输出整个序列 
template<class Iter>
void print(Iter first, Iter last, 
            const char* nm = "",
            const char* sep = "\n",
            ostream& os = cout){
    if(nm != 0 && *nm != '\0')
        os << nm << ": " << sep;
    typedef typename iterator_traits<Iter>::value_type T;
    copy(first, last, ostream_iterator<T>(cout, sep));
    os << endl;
} 

int main(int argc, char** argv) {
    const int sz = 9;
    vector<string> vs(sz);
    srand(time(0));
    NumStringGen fun(sz);
    //生成字符串,结果添加到vs 
    generate(begin(vs), end(vs), fun);//生成 
//    print(vs.begin(), vs.end());//输出生成的函数 
    
    const char* vcp[sz];
    transform(vs.begin(), vs.end(), vcp, mem_fun_ref(string::c_str)); 
    print(begin(vcp), end(vcp));
    
    //将字符换转化为小数
    vector<double> vd;
    transform(begin(vcp), end(vcp), back_inserter(vd), atof);
    print(begin(vd), end(vd));
    return 0;
}
//我们选生成了对应的字符串序列,然后再转化为数字,这里我们可以把两个操作合二为一
#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
#include<ctime>
#include<cstdlib>
#include<string>
using namespace std; 

//生成一个随机的数字字符串 
class NumStringGen{
    const int sz;
public:
    NumStringGen(int ssz): sz(ssz){}
    
    string operator()(){
        string digits("0123456789");
        const int ndigits = digits.size();
        string r(sz,' ');
        r[0] = digits[rand()% (ndigits - 1)] + 1; 
        for(int i = 0; i < sz; ++i){
            if(sz >= 3 && i == sz/2)
                r[i] = '.';
            else
                r[i] = digits[rand() % ndigits];
        }
        return r;
    }
    
}; 

//输出整个序列 
template<class Iter>
void print(Iter first, Iter last, 
            const char* nm = "",
            const char* sep = "\n",
            ostream& os = cout){
    if(nm != 0 && *nm != '\0')
        os << nm << ": " << sep;
    typedef typename iterator_traits<Iter>::value_type T;
    copy(first, last, ostream_iterator<T>(cout, sep));
    os << endl;
} 

//R是返回值的参数类型,E是函数形参类型 
template<class R, class E, class F1, class F2>
class unary_composer{
    F1 f1;
    F2 f2;
public:
    unary_composer(F1 fone, F2 ftwo): f1(fone), f2(ftwo){}
    R operator()(E x){
        return f1(f2(x));
    }
};

//函数适配器,根据生成一个函数对象,然后在对象中调用对象的函数重载 
template<class R, class E, class F1, class F2>
unary_composer<R, E, F1, F2> compose(F1 f1, F2 f2){
    return unary_composer<R, E, F1, F2>(f1, f2);
}

int main(){
    double x = compose<double, const string&>(atof, mem_fun_ref(&string::c_str))("12.34");
    cout << x << endl;
}

总结ptr_fun,mem_fun,mem_fun_ref

ptr_fun针对普通函数 fun()

mem_fun针对成员函数,但是需要指针调用 p->fun()

mem_fun_ref针对成员函数,但是不需要指针调用p.fun()

下面的代码对上面的代码进行了简单化,不需要那么多的类型推断


#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<functional>
#include<ctime>
#include<cstdlib>
#include<string>
using namespace std; 

//生成一个随机的数字字符串 
class NumStringGen{
    const int sz;
public:
    NumStringGen(int ssz): sz(ssz){}
    
    string operator()()
    {
        string digits("0123456789");
        const int ndigits = digits.size();
        string r(sz,' ');
        r[0] = digits[rand()% (ndigits - 1)] + 1; 
        for(int i = 0; i < sz; ++i)
        {
            if(sz >= 3 && i == sz/2)
                r[i] = '.';
            else
                r[i] = digits[rand() % ndigits];
        }
        return r;
    }
}; 

//输出整个序列 
template<class Iter>
void print(Iter first, Iter last, 
            const char* nm = "",
            const char* sep = "\n",
            ostream& os = cout){
    if(nm != 0 && *nm != '\0')
        os << nm << ": " << sep;
    typedef typename iterator_traits<Iter>::value_type T;
    copy(first, last, ostream_iterator<T>(cout, sep));
    os << endl;
} 

//使用继承的方式,自动推断参数的类型
template<typename F1, typename F2>
class unary_composer: public unary_function<typename F2::argument_type, typename F1::result_type >
{
    F1 f1;
    F2 f2;
public:
    unary_composer(F1 fone, F2 ftwo): f1(fone), f2(ftwo){}
    
    typename F1::result_type operator()(typename F2::argument_type x){
        return f1(f2(x));
    }
};

//函数适配器,根据生成一个函数对象,然后在对象中调用对象的函数重载 
template<class F1, class F2>
unary_composer<F1, F2> compose(F1 f1, F2 f2){
    return unary_composer<F1, F2>(f1, f2);
}

int main(){
    const int sz = 9;
    vector<string> vs(sz);
    srand(time(0));
    NumStringGen fun(sz);
    //生成字符串,结果添加到vs 
    generate(begin(vs), end(vs), fun);//生成 
//    print(vs.begin(), vs.end());//输出生成的函数 

    //将字符换转化为小数
    vector<double> vd;
    transform(begin(vs), end(vs), back_inserter(vd), compose(ptr_fun(atof), mem_fun_ref(&string::c_str)));
    print(begin(vd), end(vd));
    return 0;
}

总结函数对象适配器:

bind1st对函数的第一个参数设置

bind2nd对函数的第二个参数设置

使用的方式与自定义的一样,都是生成一个函数对象,然后调用重载函数

3.STL算法简介

3.1 迭代器

(1)InputIterator 输入迭代器,可以使用++和*来前向移动,也可以使用==和!=来判断位置

(2)OutputIterator 输出迭代器,可以++和*来前向迭代,但是不能使用==和!=,这是因为输入迭代器没有判断末尾的标志,这个经常配合back_inserter一起使用,back_inserter的返回类型就是这个

(3)ForwardIterator 前面两个迭代器只能单独写入或者输出,这个迭代器可以同时读写,而且可以使用==和!=还要++和*来进行迭代,不过这个是前向迭代器,只能++

(4)BidirectionaIterator是一个支持--的ForwordIterator

(5)RandomAccessIterator支持一切普通指针的所有操作

3.2 填充和生成

这些算法能够自动用一个值来填充容器

(1) void fill(ForwardIterator first, ForwardIterator last, const T& value);

容器开头和结尾被指定函数对象填充

(2)void file_n(ForwardIterator first, Size n,const T& value);

容器从开头到第n容器被指定函数对象填充

(3)void generate(ForwardIterator first, ForwardIterator last, Generator gen)

容器的对象挨个调用生成器,将结果保存在容器的对象中

(4)void generate_n(ForwardIterator first, Size n, Generator gen);

3.3计数

(1)IntergralValue count(InputIterator first, OutputIterator last, const EqualityComparable& value);

计算first到last等于value的数量

(2)IntergralValue count_if(InputIterator first, OutputIterator last,Predicate pred);

返回能使pred返回true的元素的个数

3.4操作序列

(1)OutputIterator copy(InputIterator first, InputIterator last, OutputIterator destination);

使用赋值,从first到last复制序列到 destination

(2) BidirectionaIterator2 copy_backward(BidirectionaIterator1 first, BidirectionaIterator1 last, BidirectionaIterator2 destinationEnd);

和copy函数一样,但是这个操作是以相反的顺序复制元素,destinationEnd是容器的末尾迭代器,容器必须有足够的空间

    int buf[] = {1,2,3,4,5,6,7,8,9,10};
    vector<int> v(10); 
    copy_backward(begin(buf), end(buf), v.end());
    print(v.begin(), v.end(),"V"," ");
    cout << endl;
 

输出 1 2 3 4 5 6 7 8 9 10

但是,它是从10开始复制倒1

(3)void reverse(BidirectionaIterator first, BidirectionaIterator last);

反转原序列

(4)BidirectionaIterator reverse_copy(BidirectionaIterator first, BidirectionaIterator last, OutputIterator destination);

复制反转序列到 destination

int main(){
int buf[] = {1,2,3,4,5,6,7,8,9,10};
vector<int> v(10);
reverse_copy(begin(buf), end(buf), v.begin());
print(v.begin(), v.end(),""," ");//输出10 9 8 7 6 5 4 3 2 1
return 0;
}

(5)ForwardIterator2 swap_ranges(ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2);

交换first和last范围内的元素

int main(){
    int buf[] = {1,2,3,4,5,6,7,8,9,10};
    vector<int> v(10);
    swap_ranges(begin(buf), end(buf), v.begin());
    print(v.begin(), v.end(),"V"," ");//输出1 2 3 4 5 6 7 8 9 10
    cout << endl;
    print(begin(buf), end(buf), "buf", " ");//输出 0 0 0 0 0 0 0 0 0 
    cout << endl;
return 0;
}

(6)void rorate(ForwardIterator first, ForwardIterator middle, ForwardIterator last);

将first到middle的序列放在last后面

vector<int> v({1,2,3,4,5,6,7,8,9,10});
 vector<int>::iterator it = v.begin();
it += 2;
rotate(begin(v), it, end(v));
print(v.begin(), v.end(),"V"," ");//输出3 4 5 6 7 8 9 10 1 2
cout << endl;

(7)OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator destination);

作用和上面一样,只不过是把结果复制到 destination

int buf[] = {1,2,3,4,5,6,7,8,9,10};
vector<int> v1;
copy(begin(buf), end(buf), back_inserter(v1));
print(v1.begin(), v1.end(),"v1"," ");//输出1 2 3 4 5 6 7 8 9 10
vector<int>::iterator it = begin(v1);
it += 4;
vector<int> v2(10);
rotate_copy(begin(v1),it,end(v1),v2.begin());
print(v1.begin(),v1.end(),"v1"," ");//输出 1 2 3 4 5 6 7 8 9 10
print(v2.begin(),v2.end(),"v2"," ");//输出 5 6 7 8 9 10 1 2 3 4
cout << endl;

下面的四个算法是排列,元素有n个,则结果有n!个组合

(8).bool next_permutation(BidirectionaIterator first, BidirectionaIterator last);

int buf[] = {1,2,3,4};
int num = 4 * 3 * 2 * 1;
for(int i = 0; i < num; i++){
next_permutation(begin(buf), end(buf));
cout << "i = " << i+1 << " ";
print(begin(buf),end(buf),"buf"," ");
}

输出24种排列,而且是以升序的方式输出

(9).bool next_permutation(BidirectionaIterator first, BidirectionaIterator last, StrictWeakOrdering binary_pred);

按照上面的是自定义的大于号运算,但是也可以用binary_pred定义,这是一个自定义的函数对象,比如可以设定为greater

(10)bool prev_permutation(BidirectionaIterator first, BidirectionaIterator last);

(11)bool prev_permutation(BidirectionaIterator first, BidirectionaIterator last, StrictWeakOrdering binary_pred);

上面四种算法其实没啥区别,第一个是升序排列,第三个是降序排列,第二,四是按照自定义的函数对象要求排列

返回值要看是否有各自的前驱或者后驱,如果没用则返回false,一般来讲是因为排列结束了才会返回false

下面两种是随机排列

(12)void random_shuffle(RandAccessIterator first, RandAccessIterator end);

使用默认的随机发生器,它会产生均匀分布的结果

int buf[] = {1,2,3,4};
for(int i = 0; i < 5; i++){
random_shuffle(begin(buf), end(buf));
print(begin(buf), end(buf),""," ");//输出的排列会被打乱
}

(13)void random_shuffle(RandAccessIterator first, RandAccessIterator end,Predicate pred)

使用用户自定义的函数对象

下面两个是划分

(14).BidirectionaIterator partition(BidirectionaIterator frist, BidirectionaIterator last, predicate pred);

序列会按照函数对象pred的要求排列,序列元素满足pred要求的排在前面,不满足的排列在后面,但是原本的相对位置可能会变化,下面的函数在实现划分规则的同时,相对位置也不会变化

函数的返回值是划分位置,这个位置前面全都满足pred的要求

int buf[] = {1,2,3,4,5,6,7,8,9,10};
print(begin(buf),end(buf),""," ");
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));
vector<int>::iterator it = partition(begin(v), end(v), bind2nd(greater<int>(),6));
cout << "分界线:" << *it << endl;
print(v.begin(), v.end(), "", " ");
return 0;

(15).BidirectionaIterator stable_partition(BidirectionaIterator frist, BidirectionaIterator last, predicate pred);

操作序列有复制,划分,排列组合,交换,颠倒。

3.5 查找与替换

(1) InputIterator find(InputIterator first, InputIterator last, cons EqualityComparable& value);

查找在first到last范围内等于value 的元素,返回第一个等于value的位置,如果不存在则返回last的位置,这是一直线性查找的方式

(2) InputIterator find_if(InputIterator first, InputIterator last, Predicate pred);

和上面那个一样,不过这次是要求函数对象,比如greater和less

(3)ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last);、

(4)ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, Predicate pred);

struct test{
    bool operator()(int m, int n){
    cout << m << " " << n << endl;
    return m == n - 1; 
    }
};
int main(){
    int buf[] = {1,2,3,3,5,6,7,8,9,10};
    print(begin(buf),end(buf),""," ");
    vector<int> v;
    copy(begin(buf), end(buf),back_inserter(v));
    vector<int>::iterator it = adjacent_find(v.begin(), v.end(), test());
    if(it == v.end()){
        cerr << "not find" << endl;
        return 0;
    }
    cout << *it << endl;
    return 0;
}

这两个函数都是查找相邻的两个相等的元素,第一个函数是调用operator==,然后返回第一个元素的位置;

第二个函数会把相等的相邻元素放入Pred对象中,然后返回true或者false,如果满足条件,则返回第一个元素的位置

(5).ForwardIterator find_first_of(ForwardIterator first1, ForwardIterator last1, forward_iterator first2, forward_iterator first2)

(6).ForwardIterator find_first_of(ForwardIterator first1, ForwardIterator last1, forward_iterator first2, forward_iterator first2, BinaryPredicate binary_pred);

这两个函数也是线性查找,查找第二个范围是否出现了第一个范围的元素,使用的是operator==,找到了则返回第一个序列的找到的位置,否则返回第一个序列的end,

不同之处在于,第二个函数会使用自定义个函数对象来定义规则

(7)ForwardIterator search(ForwardIterator first1, ForwardIterator last1, forward_iterator first2, forward_iterator first2);

(8)ForwardIterator search(ForwardIterator first1, ForwardIterator last1, forward_iterator first2, forward_iterator first2, BinaryPredicate binary_pred);

这两个函数也是线性查找,查找第二个范围的元素,是否在第一个范围的范围内,也就是第二个范围是第一个范围的子集,而且顺序也要一致,第一个函仍然是调用==,

第二个函数按照自定义的方式

找到则返回第一个序列找到的位置,找不到则返回end位置

//v1是v的一个子集

int buf[] = {1,2,3,3,5,6,1,1,15,10};
print(begin(buf),end(buf),""," ");
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));
vector<int> v2({5,6});
vector<int>::iterator b = v.begin() + 4.;
vector<int>::iterator it = search(v.begin(),v.end(), v2.begin(), v2.end());
if(it == v.end()){
cerr << "not find" << endl;
return 0;
}
   cout << *(it + 1) << endl;//找到了输出6

(9)ForwardIterator find_end(ForwardIterator first1, ForwardIterator last1, forward_iterator first2, forward_iterator first2);

(10)ForwardIterator find_end(ForwardIterator first1, ForwardIterator last1, forward_iterator first2, forward_iterator first2, BinaryPredicate binary_pred);

这两个函数与search函数差不多,只不过它查找该自己最后 出现的位置,然后返回最后位置的第一个元素的迭代器

(11)ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value);

(12)ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count,const T& value, BinaryPredicate pred);

这两个函数都是在范围里搜索连续count个与value相等的值,找到了就返回第一个相等的迭代器,找不到则返回last.

第二个稍微有点不一样的是,需要value同时满足自定义规则pred,这是一个函数对象,函数的第二个参数会接受value,而第一个参数在first中查找

第一个函数的例子

int buf[] = {1,2,3,3,5,6,1,1,15,10};
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));
print(v.begin(), v.end(),"v"," ");
vector<int>::iterator it = search_n(v.begin(),v.end(), 2,1);//查找两个连续为1的子序列
if(it == v.end()){
cerr << "not find" << endl;
return 0;
}
cout << *(it) << endl;

上面的这个程序可以查找到两个连续为1的子序列,但是找不到2以上的,当count>=3时,则会输出not found

第二个函数的例子

struct test{
bool operator()(int m, int n){
cout <<"m = " << m << " value =" << n << endl;
return m == n - 1; 
}
};
int main(){
int buf[] = {1,2,3,3,5,6,1,1,15,10};
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));
print(v.begin(), v.end(),"v"," ");
vector<int>::iterator it = search_n(v.begin(),v.end(), 2,2,test());
if(it == v.end()){
cerr << "not find" << endl;
return 0;
}
cout << *(it) << endl;
}

test的条件时m = n-1;

则程序会令n = value,也就是2, 然后查找有没有连续的两个数字满足这个条件,里面只有一个子集满足,也就是1,1

(13) ForwardIterator min_element(ForwardIterator first, ForwardIterator last)

(14)ForwardIterator min_element(ForwardIterator first, ForwardIterator last, BinaryPredicate pred);

第一个函数在范围内查找最小值,最小值可能有多个,但是返回第一个位置的迭代器,这个函数使用的时operator<

int buf[] = {1,2,3,3,5,6,1,1,15,10};
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));
print(v.begin(), v.end(),"v"," ");
vector<int>::iterator it = min_element(v.begin(),v.end());
if(it == v.end()){
cerr << "not find" << endl;
return 0;
}
cout << *(it) << endl;
//输出1 

第二个函数会使用自定义的比较规则

struct test{
bool operator()(int m, int n){
cout <<"m = " << m << " value =" << n << endl;
return m == n; 
}
};
int main(){
int buf[] = {13,2,3,3,5,6,1,1,15,10};
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));
print(v.begin(), v.end(),"v"," ");
vector<int>::iterator it = min_element(v.begin(),v.end(),test());
if(it == v.end()){
cerr << "not find" << endl;
return 0;
}
cout << *(it) << endl;
}

我在这里自定义了比较规则,使用test函数对象,且没用比较符<,而是==

则会查找与第一个元素相等的位置,但是总是返回那个元素的位置,没意义的程序,只是解释这个函数的运算规则

(13) ForwardIterator max_element(ForwardIterator first, ForwardIterator last)

(14)ForwardIterator max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate pred);

和上面一样的,只不过时查找最大值了。

(15)void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value);

(16)void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value);

(17)OutputIterator replace_copy(ForwardIterator first, ForwardIterator last, OutputIterator result,const T& old_value, const T& new_value );

(18)OutputIterator replace_copy_if(ForwardIterator first, ForwardIterator last, OutputIterator result,Predicate pred, const T& new_value );

看过前面的算法形势应该不难理解这几个算法的意义,这四个算法是替代算法

第一个函数是在范围内,将old_value替换为new_value,调用的是operator==

第二个函数是在范围内,使用自定义的规则将满足规则的元素替换为new_value

第三个函数是将old_value替换为new_value,然后把结果输入到result

第四个函数是将满足自定义条件的元素替换为new_value,然后把结果复制到result

前两个函数会对原序列更改 ,后两个不会对原序列修改,而是把结果复制到新的序列

int buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int> v;
copy(begin(buf), end(buf),back_inserter(v));//复制原序列 
print(v.begin(), v.end(),"v"," ");
vector<int> v1(v);
vector<int> v2(v);
vector<int> v3; 
vector<int> v4;
replace(v.begin(), v.end(), 3, 0);//将v的3替换为0 
print(v.begin(), v.end(),"v"," ");
replace_if(v1.begin(), v1.end(), bind2nd(less<int>(), 5), 0);//将v1小于5的数字替换为0 
print(v1.begin(), v1.end(),"v1"," ");
replace_copy(v2.begin(), v2.end(), back_inserter(v3), 4, 0);//将v2等于4的元素替换为0,并且复制到v3 
print(v2.begin(), v2.end(),"v2"," ");//v2不变 
print(v3.begin(), v3.end(),"v3"," ");//v3变换 
replace_copy_if(v2.begin(), v2.end(), back_inserter(v4), bind2nd(greater<int>(),3), 0);//将v2大于3的元素替换为0 
print(v2.begin(), v2.end(),"v2"," ");//v2不变 
print(v4.begin(), v4.end(),"v4"," ");//v4变化 

3.6 比较范围

(1) bool equal(InputIterator first1, InputIterator last1, InputIterator first2);

(2)bool equal(InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate BinaryPredicate binary_pred);

这个有点类似于search,但是search需要两个范围,查找第二个范围在第一个范围出现的位置

但是这两个函数需要两个相等的范围,指定了第一个范围,和第二个范围的开头,这是因为第二个范围需要第一个范围来设定。如果找到了,则返回true

第一个函数调用的是operator==

第二个函数调用的是自定义规则

(3)bool lexicographical_compare(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2);

(4)bool lexicographical_compare(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, BinaryPredicate binary_pred);

这两个函数是按照字典比较的顺序来判断第一个范围是否小于第二个范围,如果小于则返回true,两个范围不需要相等

char str1[] = "abc";
char str2[] = "abcd";
vector<char> v1;
vector<char> v2;
copy(begin(str1), end(str1), back_inserter(v1));
copy(begin(str2), end(str2), back_inserter(v2));
cout << lexicographical_compare(v1.begin(),v2.end(),v2.begin(),v2.end());
//输出1

(5)pair<InputIterator,InputIterator> mismatch(InputIterator first1, InputIterator last1, InputIterator first2);

(6)pair<InputIterator,InputIterator> mismatch(InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate binary_pred);

mismatch是比较两个序列不同的部分,同样需要两个长度相等的序列,然后找出序列不同的位置,返回值是pair,这是一个模板类,成员是两个迭代器,一个是first,另一个是second

返回值pair第一个值first指向第一个序列找到的地方,second指向第二个序列找到的地方

string str1 = "abcdefg";
string str2 = "abcdsss";
pair<string::iterator, string::iterator> it = mismatch(str1.begin(), str1.end(),str2.begin());
cout << "第一个位置" << *it.first << endl;
cout << "第二个位置" << *it.second << endl;

3.7 删除

删除算法的参数是迭代器。对于固定的数组来讲,是无法删除掉已经存在的空间的,所以删除算法会把删除的对象放在数组后面,而把没删除的对象放在前面,然后返回一个新的末尾迭代器。

这样,从

但是对于可变大小的序列,则能够使用erase这样的算法来删除。

(1).ForwardIterator remove(ForwardIterator first, ForwardIterator last, const&T value);

(2).ForwardIterator remove(ForwardIterator first, ForwardIterator last, predicate pred);

(3).ForwardIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const&T value);

(4).ForwardIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, predicate pred);

//1.remove
int buf[] = {1,2,3,4,5,6,7,8,9,10};
auto ptr = remove(begin(buf), end(buf), 6);
print(begin(buf), ptr(buf),""," ");
print(begin(buf),end(buf),""," ");//这里会输出1 2 3 4 5 7 8 9 10 10  
//2.remove_if
int buf[] = {1,2,3,4,5,6,7,8,9,10};
auto ptr = remove_if(begin(buf), end(buf), test());
print(begin(buf), ptr,""," ");
print(begin(buf), end(buf), "", " ");

其他的两种没有什么区别

(5). ForwardIterator unique(ForwardIterator first, ForwardIterator last);

(6). ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred);

(7). ForwardIterator unique_copy(ForwardIterator first, ForwardIterator last, OutputIterator result);

(8). ForwardIterator unique_copy(ForwardIterator first, ForwardIterator last, OutputIterator result, BinaryPredicate binary_pred);

这是一种删除相邻值相等只保留一个相等元素的算法,如果要清除序列所有的相等的值,最好先进行排序。

int buf[] = {1,2,2,4,5,6,7,8,9,10};
auto ptr = unique(begin(buf), end(buf));
print(begin(buf), ptr,""," ");
print(begin(buf), end(buf), "", " ");

3.8.排序

(1)void sort(RandAccessIterator first, RandAccessIterator last);

(2)void sort(RandAccessIterator first, RandAccessIterator last, StrictWeakOrdering binary_pred);

(3)void stable_sort(RandAccessIterator first, RandAccessIterator last);

(4)void stable_sort(RandAccessIterator first,RandAccessIterator last, StrictWeakOrdering binary_pred);

默认为升序排列,sort不是稳定排序,他可能交换相等元素的位置,stable_sort为稳定排序,保存相等元素的原位。

(5)partial_sort(RandAccessIterator first, RandAccessIterator middle, RandAccessIterator last);

(6)partial_sort(RandAccessIterator first, RandAccessIterator middle, RandAccessIterator last, StrictWeakOrdering binary_pred);

对[first, end]进行部分的排序,将排序的结果放入[first, middle)中,而对于剩下的部分,则不保证排序结果

(7)RandAccessIterator partial_sort_copy(RandAccessIterator first, RandAccessIterator last, RandAccessIterator Result_first, RandAccessIterator Result_last);

(8)RandAccessIterator partial_sort_copy(RandAccessIterator first, RandAccessIterator last, RandAccessIterator Result_first, RandAccessIterator Result_last, StrictWeakOrdering binary_pred);

对first和last范围的序列排序,并且复制到Result_first到Result_last中,如果Result_first-Result_last的范围比first-last要大,则只使用一部分排序并且复制

(9)void nth_element(RandAccessIterator first, RandAccessIterator nth, RandAccessIterator last);

(10)void nth_element(RandAccessIterator first, RandAccessIterator nth, RandAccessIterator last, StrictWeakOrdering binary_pred);

这个算法与 partial_sort有点类似,但是它比partial_sort做得工作少得多。它以nth为界,比这个数小,则放在左边,比这个数大,则放在右边

int buf[] = {1,2,3,4,5,6,7,8,9,10};
random_shuffle(begin(buf), end(buf));
print(begin(buf), end(buf), "原序列", " ");
vector<int> v(begin(buf), end(buf));
vector<int> v1(begin(buf), end(buf));
vector<int>::iterator it = v.begin();
it += 4;
partial_sort(v.begin(), it, v.end());
print(v.begin(),v.end(),"partial_sort", " ");
vector<int>::iterator v_it = v1.begin() + 4;
nth_element(v1.begin(), v_it, v1.end());
print(v1.begin(), v1.end(), "nth_element", " ");

3.9 排序之后的操作算法

以下的算法全都是排序之后的操作,如果对没有排序的序列进行操作,结果将会是未定义的

3.9.1.二分查找法

下面全部函数都是二分法,这些函数都是成对的,第一个是默认使用operator<,第二个是自定义的

(1)bool binary_search(ForwardIterator first, ForwardIterator last, const T& value);

(2)bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred);

这个算法是查找value是否存在,存在则返回true

(3)ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value);

(4)ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value,StrictWeakOrdering binary_pred);

这个算法返回value在[first, last]中第一次出现的位置,如果value不存在,则返回它应该在这个范围中的位置。

int buf[] = {1,2,3,3,5,6,7,8,9,10};
auto it = lower_bound(begin(buf), end(buf),3);
cout << *it << endl;
it = lower_bound(begin(buf), end(buf),4);
cout << *it << endl;//输出5

(3)ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value);

(4)ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value,StrictWeakOrdering binary_pred);

返回value后一个位置,如果value不存在,则返应该出现的位置

int buf[] = {1,2,3,3,5,6,7,8,9,10};
auto it = upper_bound(begin(buf), end(buf),3);
cout << *it << endl;
it = upper_bound(begin(buf), end(buf),3);
cout << *it << endl;

(5)pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value);

(6)pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred);

这个函数是lower_bound和upper_bound的结合,first指向value第一次出现的位置,second指向value最后一次出现的位置

3.9.2 合并算法

下面几个算法是合并算法,下面的函数也是成对的,合并之后的序列仍然是排序过的

(1). OutputIterator merge(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result);

(2). OutputIterator merge(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result, StrictWeakOrdering binary_pred);

将[first1,last1],[first2, last2]复制到result中,结果将是升序的,自定义的不一样

(3)void inplace_merge(BidirectionaIterator first, BidirectionaIterator middle, BidirectionaIterator last );

(4)void inplace_merge(BidirectionaIterator first, BidirectionaIterator middle, BidirectionaIterator last, StrictWeakOrdering binary_pred);

这里假定[first, middle)和[middle,last)来自同一个序列已排序好的,然后把结果保存在[first,last],则原序列为升序的序列

3.9.3 集合算法

对已排序的序列进行集合操作,输出的结果仍然是排序好的

1.包含

(1).bool includes(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2);

(2).bool includes(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, StrictWeakOrdering binary_pred);

如果[first2, last2)是[first1, last1)的子集,则返回true

2.并集

(3)OutputIterator set_union(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result);

(4)OutputIterator set_union(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result);

结果保存在result中,返回末尾的迭代器,如果某个元素在一个集合中出现多次,则result保存出现次数多的集合

3.交集

(5).OutputIterator set_intersection(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result);

(6).OutputIterator set_intersection(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result, StrictWeakOrdering binary_pred);

结果保存在result中,返回末尾的迭代器,如果某个元素在其中一个序列中出现多次,则result保存出现次数少的序列

4.集合的差

(7).OutputIterator set_difference(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result);

(8).OutputIterator set_difference(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result, StrictWeakOrdering binary_pred);

计算两个范围之间的集合差,这个差代表在第一个范围中出现,但是不在第二个范围中。如果某个元素多次出现,比如在第一个范围中出现n次,但是在第二个范围中出先m次,则结果中只保存max(n-m,0)次

int buf1[] = {1,2,3,3,5,6,7,8,9,10};
int buf2[] = {1,3,3,100};
vector<int> result;
auto ptr = set_difference(begin(buf1), end(buf1), begin(buf2), end(buf2), back_inserter(result));
print(result.begin(), result.end(),""," ");

(7).OutputIterator set_symmetric_difference(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result);

(8).OutputIterator set_symmetric_difference(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, OutputIterator result, StrictWeakOrdering binary_pred);

这个差集的结果是相当于二者求并集,然后分别求差集的结果,也就是result包含的是

1.集合1中有的元素,但是集合2中没有;

2.集合2中有的元素集合1中没有

4 堆运算

下面每一种算法都成对的出现,第一种是默认使用operator<,第二种是自定义的函数对象

1.创建堆

(1)void make_heap(RandAccessIterator first, RandAccessIterator last);

(2)void make_heap(RandAccessIterator first, RandAccessIterator last, StrictWeakOrdering binary_pred);

2.将最后一个元素添加到堆中合适的位置

(3)void push_heap(RandAccessIterator first, RandAccessIterator last);

(4)void push_heap(RandAccessIterator first, RandAccessIterator last, StrictWeakOrdering binary_pred);

这个就相当于添加元素到堆中,不过由于是针对序列的,序列可能无法再次扩充,所有才会没有const T&的形式

3.获取堆顶元素

(5)void pop_heap(RandAccessIterator first, RandAccessIterator last);

(6)void pop_heap(RandAccessIterator first, RandAccessIterator last, StrictWeakOrdering binary_pred);

堆顶的元素成为了first-1,而原来的堆顶到了序列的末尾

4.堆排序

这是对已经存在的堆进行的排序,对于排序之后的序列,它将不在是堆,所以使用pop_heap和push_pop毫无意义

(7)void sort_heap(RandAccessIterator first, RandAccessIterator last);

(8)void sort_heap(RandAccessIterator first, RandAccessIterator last, StrictWeakOrdering binary_pred);

int buf[] = {1,2,3,3,5,6,7,8,9,10};
vector<int> result;
random_shuffle(begin(buf), end(buf));//随机化 
copy(begin(buf), end(buf), back_inserter(result));
print(result.begin(), result.end(),"result原始数据"," ");
make_heap(result.begin(), result.end()-1);//[first, end-1)转化为堆 
print(result.begin(), result.end(),"对[first, end-1)转化为堆"," ");
push_heap(result.begin(), result.end());//将序列最后一个元素添加到堆中
print(result.begin(), result.end(),"添加末尾元素到堆"," ");
vector<int> v(result);//复制堆 
pop_heap(result.begin(), result.end());//将序列最后一个元素添加到堆中
print(result.begin(), result.end(),"堆顶元素出堆"," ") ;
sort_heap(v.begin(), v.end());
print(v.begin(), v.end(),"对堆进行排序"," ") ;

5 对某一范围的所有元素进行运算

(1).UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);

(2).OutputIterator transform(InputIterator first. InputIterator last, OutputIterator result, UnaryFunction f);

(3).OutputIterator transform(InputIterator first. InputIterator last,InputIterator first2, OutputIterator result, UnaryFunction f);

for_each函数执行的是f(*first);他会丢弃掉的函数的返回值,但是会把函数给返回过来,程序员可以通过返回的函数对象来获取状态;

第一个transform执行的是f(*first),并且把结果保存在result中

第二个函数是执行f(*first1,first2);两个序列的范围要相等,第二个序列的范围由第一个决定

6.数值计算

1.求和

(1)T accumulate(InputIterator first, InputIterator last, T result);

执行的过程是 result += *first

(2)T accumulate(InputIterator first, InputIterator last,T result, BinaryPredicate f);

执行过程是 f(result, *first)

返回值是运算的结果

struct f{
    int operator()(int& y,int& x){
        y += x*x;
        return y;
        }
};
int main(int argc, char** argv) {
    int buf[] = {1,2,3,4,5,6,7,8,9,10};
    int sum = 0;
    sum = accumulate(begin(buf), end(buf), 0);
    cout << sum << endl;//55
    sum = accumulate(begin(buf), end(buf), 0, f());//f(0, buf[i])
    cout << sum << endl;//1 + 4 + 9 + 16 + ... + 100
    return 0;
}

2.内积

(3).T inner_product(InputIterator first1, InputIterator last1, InputIterator first2, T init);

(4).T inner_product(InputIterator first1, InputIterator last1, InputIterator first2, T init, BinaryFunction op1, BinaryFunction op2);

init代表一个初始值

op1代替了加法,op2代替乘法

第一种默认的内积算法是 (*first1) * (*first2)

那么第二种是 op1(init,op2(first1,first2));

返回值是运算的结果

struct a{
    int operator()(int& x, int y)
    {//这里x使用引用,是因为这个值会被累加,必须保留
        cout << x << "+" << y << endl;
        x = x + y;
        return x;
    }
};
struct m{
    int operator()(int x, int y)
    {
        cout << x << "*" << y << endl;
        return x * y;
    }
};
int main(int argc, char** argv) {
    int buf[] = {1,2,3,4,5,6,7,8,9,10};
    int arr[] = {1,1,1,1,1,1,1,1,1,1};
    int sum = inner_product(begin(buf), end(buf), begin(arr), 0);
    cout << sum << endl;
    sum = inner_product(begin(buf), end(buf), begin(arr), 0, a(), m());
    cout << sum << endl;
    return 0;
}

3.部分和

(5)OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result);

(6)OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred);

这个累积和与一般的不一样,它是一种斐波拉契模式的累计

返回值为result容器的末尾

4.相邻差

(7)OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result);

(8)OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred);

第一个元素不变,其他都是后面一个元素减去前一个元素

template<class Iter>
void print(Iter first, Iter last, 
const char* nm = "",
const char* sep = "\n",
ostream& os = cout)
{
    if(nm != 0 && *nm != '\0')
    os << nm << ": " << sep;
    typedef typename iterator_traits<Iter>::value_type T;
    copy(first, last, ostream_iterator<T>(cout, sep));
    os << endl;
} 
struct m{
    int operator()(int x, int y){
        return x * y;
    }
};
int main(int argc, char** argv) {
    int buf[] = {1,2,3,4,5,6,7,8,9,10};
    vector<int> result;
    adjacent_difference(begin(buf), end(buf), back_inserter(result));
    print(result.begin(), result.end(), "", " ");
    result.clear();
    adjacent_difference(begin(buf), end(buf), back_inserter(result), m());//自定义计算方法,变成了后一个数字乘以前一个数字
    print(result.begin(), result.end(), "", " ");
    return 0;
}

7. 通用实用工具

1. 关联对象

template<class T1, class 2> struct pair//关联对象的定义

创建一个关联对象可以使用make_pair(const T1&. const T2&);

获取关联对象可以使用first和second;

2.两个迭代器的之间的距离,计算需要迭代多少次

difference_type distance(InputIterator first, InputIterator last);

返回值一般是整型

3.给容器创建迭代器用于插入

back_insert_iterator<Container> back_inserter(Container& x);

front_insert_iterator<Container> front_inserter(Container& x);

insert_iterator<Container> inserter(Container& x, Iterator i);

4.返回较小值

const T& min(const T&, const T&);

5返回较大值

const T& max(const T&, const&T);

6.交换值

void swap(T&a , T& b);

每一种容器实际上都有自己的特化版本的交换算法,最好用特化版的

void iter_swap(ForwardIterator a, ForwardIterator b);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值