09-C++ STL-适配器、算法

c++ STL-适配器、算法

1. 函数对象

1.1 概念

重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor), 其实就是 重载“()”操作符使得 类对象 可以 像函数 那样调用

作用:为算法提供策略。

注意:

  1. 函数对象(仿函数)是一个类,不是一个函数。
  2. 函数对象(仿函数)重载了”() ”操作符使得它可以像函数一样调用。

1.2 函数对象的分类

一元仿函数(unary_functor): 重载的 operator()要求获取一个参数
二元仿函数(binary_functor): 重载的operator()要求获取两个参数

1.3 示例

#include 

using namespace std;
class Add{
public:
    void operator ()(int a, int b)
    {
        cout << a + b << endl;
    }
};

int main(int argc, char *argv[])
{
    Add add01;
    add01(1,3); //4
    add01(4,5); //9

    //匿名对象
    Add()(5,6); //11
    return 0;
}

【小结】:

1、函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。
2、函数对象超出普通函数的概念,函数对象可以有自己的状态
3、函数对象可内联编译、性能好,用函数指针几乎不可能
4、模版函数对象使函数对象具有通用性,这也是它的优势之一

2. 谓词

谓词是 指 普通函数重载的 operator() 返回值是 bool 类型的函数对象(即仿函数),依据函数接收的参数又分为 一元谓词二元谓词 等,谓词可作为一个判断式。

  • 有一个参数 叫 一元谓词。
  • 有二个参数 叫 二元谓词。

如:

gt 大于, ge 大于等于, lt小于, le小于等于, eq 等于, ne 不等于

示例:

#include 

using namespace std;
//这种函数被称为一元谓词
bool isCN(int age)
{
    if(age >= 18)
    {
        return true;
    }
    return false;
}
//这种函数被称为二元谓词
bool test(int a,int b){
    return false;
}

class A{
public:
    bool operator()(int a){

    }
};

class B{
public:
    bool operator()(int a,int b){

    }
};
int main(int argc, char *argv[])
{
    A()(1);
    B()(1,3);
    return 0;
}

3. 内建函数

引入头文件

#include 

STL 内建了一些函数对象, 分为 算数类函数对象关系运算类函数对象逻辑运算类仿函数等。这些仿函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。

3.1 算数类函数对象

template<class T> T plus<T>//加法仿函数
template<class T> T minus<T>//减法仿函数
template<class T> T multiplies<T>//乘法仿函数
template<class T> T divides<T>//除法仿函数
template<class T> T modulus<T>//取模仿函数
template<class T> T negate<T>//取反仿函数

6 个算数类函数对象,除了 negate 是一元运算,其他都是二元运算。

示例1:

#include 
using namespace std;
void fun01()
{
    /*
template T plus//加法仿函数
template T minus//减法仿函数
template T multiplies//乘法仿函数
template T divides//除法仿函数
template T modulus//取模(取余)仿函数
template T negate//取反仿函数
    */
    int num01 = plus<int>()(1,5);
    cout << num01 << endl;      //6
    plus<int> pl;
    int num02 = pl(2,6);
    cout << num02 << endl;      //8

    cout << minus<double>()(5,1) << endl;   //4
    cout << multiplies<double>()(5,2) << endl;  //10
    cout << divides<int>()(5,2) << endl;    //2
    cout << modulus<int>()(5,2) << endl;    //1
    cout << negate<int>()(5) << endl;       //-5
    cout << negate<int>()(-5) << endl;      //5
}

示例2:自定义

template<class X>
class Add{
public:
    X operator()(X x1,X x2)
    {
        return x1+x2;
    }
};
void fun04()
{
    cout << Add<int>()(1,4) << endl;
}

3.2 关系运算类函数对象

template<class T> bool equal_to<T>//等于
template<class T> bool not_equal_to<T>//不等于
template<class T> bool greater<T>//大于
template<class T> bool greater_equal<T>//大于等于
template<class T> bool less<T>//小于
template<class T> bool less_equal<T>//小于等于

6 个关系运算类函数对象,每一种都是二元谓词

示例1:普通比较

void fun02()
{
    /*
template bool equal_to//等于
template bool not_equal_to//不等于
template bool greater//大于
template bool greater_equal//大于等于
template bool less//小于
template bool less_equal//小于等于
    */
    cout << equal_to<int>()(10,10) << endl;     //1
    cout << equal_to<int>()(10,1) << endl;      //0 
    cout << not_equal_to<int>()(10,1) << endl;  //1
    cout << greater<int>()(10,1) << endl;       //1
    cout << greater_equal<int>()(10,1) << endl; //1
    cout << greater_equal<int>()(10,10) << endl;    //1
    cout << greater_equal<int>()(10,11) << endl;    //0
    cout << less<int>()(10,1) << endl;              //0
    cout << less_equal<int>()(10,11) << endl;       //1
}

示例2:应用于比较

#include 
using namespace std;
#include 
#include 
void fun03()
{
    int nums[] = {99,24,54,12,5,7,89,66};
    vector<int> vs;
    vs.assign(nums,nums+8);
    //两参
    //sort(vs.begin(),vs.end());
    //三参,有比较
    sort(vs.begin(),vs.end(),greater<int>());
    //遍历输出,lambad表达式
    for_each(vs.begin(),vs.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}
//99 89 66 54 24 12 7 5

3.3 逻辑运算类运算函数

template<class T> bool logical_and<T>//逻辑与
template<class T> bool logical_or<T>//逻辑或
template<class T> bool logical_not<T>//逻辑非

3个逻辑运算类运算函数,not 为一元谓词,其余为二元谓词。

4. 适配器

绑定

bind2nd将绑定的数据放置第二个参数位置
bind1st将绑定的数据放置第一个参数位置

bind1st和bind2nd 将二元函数对象转为一元函数对象

4.1 引入

现在我有这个需求 在遍历容器的时候,我希望将容器中的值全部加上 100 之后显示出来,怎么做?

尝试:

//1.直接在打印时+100
void fun01()
{
    vector<int> vs;
    vs.push_back(10);
    vs.push_back(30);
    vs.push_back(50);

    //1、迭代器打印输出
    vector<int>::iterator it = vs.begin();
    for(; it != vs.end(); it++)
    {
        cout << *it + 100 << " ";
    }
    cout << endl;
}
//110 130 150 

需要我们自己的函数对象继承 binary_function 或者 nary_function

4.2 函数指针适配器

4.2.1 特点

普通函数地址 作为适配器

  • 应用 ptr_fun(函数名)
  • 【注意】仿函数的参数不能使用引用
4.1.3 示例
void print01(int v)
{
    cout << v+100 << " ";
}
void print02(int v,int x)
{
//    cout << v + x << " ";
    //证明绑定参数位置
    cout << v << " " << x << " ";
}
void fun02()
{
    vector<int> vs;
    vs.push_back(10);
    vs.push_back(30);
    vs.push_back(50);
    //2、STL提供的算法for_each遍历
    //2.1 普通函数+100 写死直接遍历
    for_each(vs.begin(), vs.end(), print01);
    cout << endl;
    //2.2 适配器,
    //print02此时为全局函数,所以此处是函数指针适配器, bind1st绑定在第一个参数上
    for_each(vs.begin(), vs.end(), bind1st(ptr_fun(print02), 100));
    cout << endl;
    //bind1st绑定在第二个参数上
    for_each(vs.begin(), vs.end(), bind2nd(ptr_fun(print02), 100));
    cout << endl;
}
//110 130 150 
//100 10 100 30 100 50 
//10 100 30 100 50 100 

4.2 函数对象适配器

4.2.1 特点

函数对象 作为适配器。

for_each(v.begin(), v.end(), bind1st(函数对象类(), x));
for_each(v.begin(), v.end(), bind2nd(函数对象类(), x));
4.2.2 步骤

1、创建一个类,使其公共继承 binary_function,并进行参数萃取

  • 参数萃取:
    • 模板中第一个类型 T1 为重载函数调用运算符 第一个参数 的数据类型
    • 模板中第二个类型 T2 为重载函数调用运算符 第二个参数 的数据类型
    • 模板中第二个类型 T3 为重载函数调用运算符 返回值 的数据类型

2、const修饰 重载函数调用运算符,即()

3、使用bindxxx绑定函数对象与适配器

示例:

//步骤1,定义一个类,使其公共继承与binary_function,并进行参数萃取
//参数萃取
//binary_function的三个模板类型分别为
//1,重载的函数调用运算符第一个形参的数据类型
//2,重载的函数调用运算符第二个形参的数据类型
//3,重载的函数调用运算符的返回值类型
class MyPrint01:public binary_function<int,int,void>{
public:
    //步骤2:重载函数调用运算符并使用const修饰
    void operator()(int v,int x) const
    {
        cout << v + x << " ";
    }
};
void fun03()
{
    vector<int> vs;
    vs.push_back(10);
    vs.push_back(20);
    vs.push_back(30);
    vs.push_back(40);
    vs.push_back(50);
    //步骤3:使用函数对象作为适配器时,需要使用bindxxx进行绑定
    for_each(vs.begin(),vs.end(),bind2nd(MyPrint01(),100));
    cout << endl;
}
//110 120 130 140 150

示例2:本月所有员工工资加2000奖金

class Staff{
    string name;
    double money;
public:
    Staff(){}
    Staff(string name,double money)
    {
        this->name = name;
        this->money = money;
    }
    string getName()
    {
        return name;
    }
    double getMoney()
    {
        return money;
    }
};
class PrintStaffInfo:public binary_function<Staff,int,void>{
public:
    void operator()(Staff s,int money) const
    {
        cout << s.getName() << " " << s.getMoney() + money << endl;
    }
};
void fun04()
{
    vector<Staff> stas;
    stas.push_back(Staff("张三",3100));
    stas.push_back(Staff("李四",3200));
    stas.push_back(Staff("王五",3000));
    stas.push_back(Staff("马六",10000));
	//将遍历出的数据作为参数传递给函数
    for_each(stas.begin(),stas.end(),bind2nd(PrintStaffInfo(),2000));
}
//张三 5100
//李四 5200
//王五 5000
//马六 12000

4.3 成员函数适配器

4.3.1 特点
  • 成员函数地址 作为适配器
  • mem_fun_ref(&类名::函数名)
4.3.2 示例

本月所有员工工资加2000奖金

class Staff02{
    string name;
    double money;
public:
    Staff02(){}
    Staff02(string name,double money)
    {
        this->name = name;
        this->money = money;
    }
    void print()
    {
        cout << name << " " << money << endl;
    }
    void print02(int m)
    {
        cout << name << " " << money + m << endl;
    }
};

void fun06()
{
    vector<Staff02> stas;
    stas.push_back(Staff02("张三",3100));
    stas.push_back(Staff02("李四",3300));
    stas.push_back(Staff02("王五",2100));
    //使用遍历出的数据调用传入的函数
    //for_each(stas.begin(),stas.end(),mem_fun_ref(&Staff02::print));
    //此时print02 只有一个形参,使用bind2nd绑定,会将实参绑定在这一个形参上,
    //遍历出来的数据就是第一个参数,因为是它调用函数,所以省略不写,不能使用bind1st,会报错
    for_each(stas.begin(),stas.end(),bind2nd(mem_fun_ref(&Staff02::print02),2000));
}

//张三 5100
//李四 5300
//王五 4100

4.4 取反适配器

1)定义 unary_function 的函数对象类

2)应用

find_if(v.begin(), v.end(), 函数对象类());
find_if(v.begin(), v.end(), not1(函数对象类()));
// 动态给定条件
find_if(v.begin(), v.end(), not1(bind2nd(greater<int>(),5)));
sort(v.begin(), v.end(), not2(less<int>()));
// 匿名函数
for_each(v.begin(), v.end(), [](int val){cout << val << " "; });

其中的 not1 对一元函数对象取反,,not2 对二元函数对象取反。

示例:

void fun07()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(40);
    nums.push_back(50);
    //查找30
    vector<int>::iterator it = find(nums.begin(),nums.end(),30);
    cout << (*it) << endl;
    //查找大于30
    vector<int>::iterator it02 = find_if(nums.begin(),nums.end(),bind2nd(greater<int>(),30));
    cout << (*it02) << endl;
    //查找小于30
    vector<int>::iterator it03 = find_if(nums.begin(),nums.end(),bind2nd(less<int>(),30));
    cout << (*it03) << endl;
    //查找大于30,然后取反,得到小于30的
    vector<int>::iterator it04 = find_if(nums.begin(),nums.end(),not1(bind2nd(greater<int>(),30)));
    cout << (*it04) << endl;
}
//30
//40
//10
//10

示例2:自定义二元适配器仿函数,实现查找大于n的第一个容器元素, 尝试反适配

#include 
#include 
#include 
class GtN : public binary_function<int, int, bool>{ 
public:
    bool operator()(const int &n1, const int &n2) const
    {
    	return n1 > n2;
    }
};
int main(int argc, char const *argv[])
{
    int m[] = {1, 2, 2, 3, 5, 10};
    vector<int> v(m, m + 6);
    // find_if(start, end, callback) 返回查找到的第一个元素的地址;
    vector<int>::iterator it = find_if(v.begin(), v.end(), not1(bind2nd(GtN(), 1)));
    cout << *it << endl;
    return 0;
}
//1

5. 常用算法

算法中常用的功能涉及到比较、交换、查找、遍历、复制,修改,反转,排序,合并等。

引入头文件

#include 

5.1 遍历

5.1.2 for_caeh

语法:

/* 
遍历算法 遍历容器元素
@param beg 开始迭代器
@param end 结束迭代器
@param _callback 函数回调或者函数对象
@return 函数对象
*/
for_each(iterator beg, iterator end, _callback);

示例1:遍历普通类型

#include 
#include 
#include 
using namespace std;
void print01(int v)
{
    cout << v << " " << endl;
}
void fun01()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(40);
    nums.push_back(50);

    //for_each(nums.begin(),nums.end(),print01);
    //lambad表达式
    for_each(nums.begin(),nums.end(),[](int v)
    {
        cout << v << " ";
    });
    cout  << endl;
}
//10 20 30 40 50

int main(int argc, char *argv[])
{
    fun01();
    return 0;
}

示例1:遍历自定义类型

class Person{
    friend void printPerson(Person p);
    string name;
    int age;
public:
    Person(){}
    Person(string name,int age){
        this->name = name;
        this->age = age;
    }
};
void printPerson(Person p)
{
    cout << p.name << " " << p.age << endl;
}

void fun02()
{
    vector<Person> ps;
    ps.push_back(Person("张三",18));
    ps.push_back(Person("李四",18));
    ps.push_back(Person("王五",18));
    ps.push_back(Person("马六",18));
    ps.push_back(Person("候七",18));

    for_each(ps.begin(),ps.end(),printPerson);
}
//张三 18
//李四 18
//王五 18
//马六 18
//候七 18
5.1.3 transform

将指定容器区间元素 搬运 到另一容器中。

【注意】不会给目标容器分配内存,所以需要我们 提前分配好内存

语法:

/*
transform 算法 将指定容器区间元素搬运到另一容器中
注意:transform 不会给目标容器分配内存,所以需要我们提前分配好内存
@param beg1 源容器开始迭代器
@param end1 源容器结束迭代器
@param beg2 目标容器开始迭代器
@param _cakkback 回调函数或者函数对象
@return 返回目标容器迭代器
*/
transform(iterator beg1, iterator end1, iterator beg2, _callbakc);

/*
transform 算法 将指定容器区间元素搬运到另一容器中
注意:transform 不会给目标容器分配内存,所以需要我们提前分配好内存
@param beg1 源容器1开始迭代器
@param end1 源容器1结束迭代器
@param beg2 源容器2开始迭代器
@param result 结果
@param _cakkback 回调函数或者函数对象
@return 返回目标容器迭代器
*/
transform(iterator beg1, iterator end1, iterator beg2,iterator result,_callbakc);

示例:

void print01(int v)
{
    cout << v << " " << endl;
}
int setData(int v)
{
    return v;
}
int setData2(int v)
{
    return v+100;
}
void fun04()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(40);
    nums.push_back(50);

    vector<int> ns;
    //设置大小
    ns.resize(nums.size());
    //transform(nums.begin(),nums.end(),ns.begin(),setData);
    //中间可以加工数据
    transform(nums.begin(),nums.end(),ns.begin(),setData2);
    for_each(ns.begin(),ns.end(),print01);
}
//110
//120
//130
//140
//150

5.2 查找

5.2.1 find

作用:查找

语法:

/*
find 算法 查找元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return 返回查找到元素对应的迭代器
*/
find(iterator beg, iterator end, value)

示例:

void fun05()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(40);
    nums.push_back(50);

    vector<int>::iterator it = find(nums.begin(),nums.end(),30);
    cout << *it << endl;
}
//30
5.2.2 find_if

作用:条件查找

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 回调函数或者谓词(返回 bool 类型的函数对象)
@return 返回查找到元素对应的迭代器,找不到返回随机值
*/
find_if(iterator beg, iterator end, _callback)

示例:

void fun06()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(40);
    nums.push_back(50);

    vector<int>::iterator it = find_if(nums.begin(),nums.end(),bind2nd(greater<int>(),20));
    cout << *it << endl;
}
//30
5.2.3 adjacent_find

作用:查找相邻重复元素

/**
*adjacent_find算法 查找相邻重复元素
*@param beg容器开始迭代器
*@param end容器结束迭代器
*@param _callback回调函数或者谓词(返回bool类型的函数对象)
*@return返回相邻元素的第一个位置的迭代器
**/
adjacent_find(iterator beg, iterator end, _callback);

示例:

void fun07()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(10);
    nums.push_back(30);
    nums.push_back(30);
    nums.push_back(40);

    vector<int>::iterator it = adjacent_find(nums.begin(),nums.end());
    cout << *it << endl;
}
//10
5.2.4 binary_search

作用:二分查找 (必须有序)

/* 
注意: 在无序序列中不可用
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return bool 查找返回 true 否则 false
*/
bool binary_search(iterator beg, iterator end, value);

示例:

void fun08()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(10);
    nums.push_back(30);
    nums.push_back(30);
    nums.push_back(40);

    bool b = binary_search(nums.begin(),nums.end(),20);
    cout << b << endl;
    bool b2 = binary_search(nums.begin(),nums.end(),30);
    cout << b2 << endl;
}
//0
//1
5.2.5 count

作用:统计

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 回调函数或者谓词(返回 bool 类型的函数对象)
@return int 返回元素个数
*/
count(iterator beg, iterator end, value);

示例:

void fun09()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(10);
    nums.push_back(30);
    nums.push_back(30);
    nums.push_back(10);

    int c = count(nums.begin(),nums.end(),10);
    cout << c << endl;
}
//3
5.2.6 count_if

作用:条件统计

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 回调函数或者谓词(返回 bool 类型的函数对象)
@return int 返回元素个数
*/
count(iterator beg, iterator end, value);

示例:

void fun10()
{
    vector<int> nums;
    nums.push_back(10);
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(10);

    int c = count_if(nums.begin(),nums.end(),bind2nd(greater<int>(),20));
    cout << c << endl;
}
//1

5.3 排序

/*
merge 算法 容器元素合并,并存储到另一容器中
注意:两个容器必须是有序的
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
*/
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
    
/*
sort 算法 容器元素排序
@param beg 容器 1 开始迭代器
@param end 容器 1 结束迭代器
@param _callback 回调函数或者谓词(返回 bool 类型的函数对象)
*/
sort(iterator beg, iterator end, _callback)
    
/*
random_shuffle 算法 对指定范围内的元素随机调整次序
@param beg 容器开始迭代器
@param end 容器结束迭代器
*/
random_shuffle(iterator beg, iterator end)
    
/*
reverse 算法 反转指定范围的元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
*/
reverse(iterator beg, iterator end)

示例:

#include 
#include 
#include 
using namespace std;
void fun11()
{
    vector<int> nums;
    nums.push_back(20);
    nums.push_back(30);
    nums.push_back(40);
    nums.push_back(10);
    nums.push_back(50);

    vector<int> nums02;
    nums02.push_back(70);
    nums02.push_back(90);
    nums02.push_back(60);
    nums02.push_back(80);
    nums02.push_back(100);

    vector<int> nums03;
    nums03.resize(nums.size() + nums02.size());
    //合并
    merge(nums.begin(),nums.end(),nums02.begin(),nums02.end(),nums03.begin());
    for_each(nums03.begin(),nums03.end(),[](int v){
       cout << v << " ";
    });
    cout << endl;
    cout << "####################" << endl;
    //排序
    sort(nums03.begin(), nums03.end());
    for_each(nums03.begin(),nums03.end(),[](int v){
       cout << v << " ";
    });
    cout << endl;
    cout << "####################" << endl;
    //打乱顺序
    random_shuffle(nums03.begin(),nums03.end());
    for_each(nums03.begin(),nums03.end(),[](int v){
       cout << v << " ";
    });
    cout << endl;
}

void fun12()
{
    vector<int> vs;
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);

    //逆序数字
    reverse(vs.begin(),vs.end());
    for_each(vs.begin(),vs.end(),[](int v){
       cout << v << " ";
    });
    cout << endl;

    string str = "hello";
    //逆序字符串
    reverse(str.begin(),str.end());
    cout << str << endl;
}
int main(int argc, char *argv[])
{
    fun11();
    cout << "--------------" << endl;
    fun12();
    return 0;
}

//20 30 40 10 50 70 90 60 80 100 
//####################
//10 20 30 40 50 60 70 80 90 100 
//####################
//90 20 100 30 10 60 80 40 50 70 
//--------------
//3 2 1 
//olleh

5.4 拷贝与替换

/*
copy 算法 将容器内指定范围的元素拷贝到另一容器中
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param dest 目标起始迭代器
*/
copy(iterator beg, iterator end, iterator dest)
/*
replace 算法 将容器内指定范围的旧元素修改为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param oldvalue 旧元素
@param oldvalue 新元素
*/
replace(iterator beg, iterator end, oldvalue, newvalue)
/*
replace_if 算法 将容器内指定范围满足条件的元素替换为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 函数回调或者谓词(返回 Bool 类型的函数对象)
@param oldvalue 新元素
*/
replace_if(iterator beg, iterator end, _callback, newvalue)
/*
swap 算法 互换两个容器的元素
@param c1 容器 1
@param c2 容器 2
*/
swap(container c1, container c2)

示例:

void fun13()
{
    vector<int> vs;
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);
    list<int> ls;
    //指定大小
    ls.resize(3);
    copy(vs.begin(),vs.end(),ls.begin());
    
    for_each(ls.begin(),ls.end(),[](int v){
       cout << v << " ";
    });
    cout << endl;
}

void fun14()
{
    vector<int> vs;
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);

    replace(vs.begin(),vs.end(),2,22);
    for_each(vs.begin(),vs.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}

void fun15()
{
    vector<int> vs;
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);

    replace_if(vs.begin(),vs.end(),bind2nd(greater<int>(),1),100);

    for_each(vs.begin(),vs.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}

//1 2 3 
//--------------
//1 22 3 1 22 3 
//--------------
//1 100 100 1 100 100 

5.5 算数生成

/*
accumulate 算法 计算容器元素累计总和
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 累加值, 额外加的值,可以为0
@return 累加后的数值
*/
accumulate(iterator beg, iterator end, value)
/*
fill 算法 向容器中添加元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value t 填充元素
*/
fill(iterator beg, iterator end, value)

示例:

void fun16()
{
    vector<int> vs;
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);
    vs.push_back(1);
    vs.push_back(2);
    vs.push_back(3);
	//元素累计总和
    int num = accumulate(vs.begin(),vs.end(),0);
    cout << num << endl;
}
void fun17()
{
    vector<int> vs;
    vs.resize(10);
    //容器前5个位置填充10
    fill(vs.begin(),vs.end()-5,10);
    for_each(vs.begin(),vs.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}

//12
//--------------
//10 10 10 10 10 0 0 0 0 0 

5.6 集合算法

/*
set_intersection 算法 求两个 set 集合的交集
注意:两个集合必须是有序序列
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_intersection(iterator beg1, iterator end1, iterator beg2, iteratorend2, iterator dest)
    
/*
set_union 算法 求两个 set 集合的并集
注意:两个集合必须是有序序列
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
    
/*
set_difference 算法 求两个 set 集合的差集
注意:两个集合必须是有序序列
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

示例:

//交集
void fun18()
{
    vector<int> ns1;
    ns1.push_back(1);
    ns1.push_back(3);
    ns1.push_back(5);
    ns1.push_back(7);
    ns1.push_back(9);

    vector<int> ns2;
    ns2.push_back(7);
    ns2.push_back(9);
    ns2.push_back(11);
    ns2.push_back(13);

    //求交集
//    set s;
//    vector::iterator it1 = ns1.begin();
//    for(;it1 != ns1.end();it1++)
//    {
//        vector::iterator it2 = ns2.begin();
//        for(;it2 != ns2.end();it2++)
//        {
//            if(*it1 == *it2)
//            {
//                s.insert(*it1);
//            }
//        }
//    }
    vector<int> s;
    set_intersection(ns1.begin(),ns1.end(),
                     ns2.begin(),ns2.end(),
                     back_inserter(s));
    for_each(s.begin(),s.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}
//并集
void fun19()
{
    vector<int> ns1;
    ns1.push_back(1);
    ns1.push_back(3);
    ns1.push_back(5);
    ns1.push_back(7);
    ns1.push_back(9);

    vector<int> ns2;
    ns2.push_back(7);
    ns2.push_back(9);
    ns2.push_back(11);
    ns2.push_back(13);

    vector<int> s;
    set_union(ns1.begin(),ns1.end(),
              ns2.begin(),ns2.end(),back_inserter(s));
    for_each(s.begin(),s.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}
//差集
void fun20()
{
    vector<int> ns1;
    ns1.push_back(1);
    ns1.push_back(3);
    ns1.push_back(5);
    ns1.push_back(7);
    ns1.push_back(9);

    vector<int> ns2;
    ns2.push_back(7);
    ns2.push_back(9);
    ns2.push_back(11);
    ns2.push_back(13);

    vector<int> s;
    //1对2取差集
    //set_difference(ns1.begin(),ns1.end(),ns2.begin(),ns2.end(),back_inserter(s));
    //2对1取差集
    set_difference(ns2.begin(),ns2.end(),ns1.begin(),ns1.end(),back_inserter(s));
    for_each(s.begin(),s.end(),[](int v){
        cout << v << " ";
    });
    cout << endl;
}

//7 9 
//--------------
//1 3 5 7 9 11 13 
//--------------
//11 13 

你可能感兴趣的:(C/C++,c++,算法,开发语言)