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

c++ STL-适配器、算法

1. 函数对象

1.1 概念

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

作用:为算法提供策略。

注意:

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

1.2 函数对象的分类

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

1.3 示例

#include <iostream>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); //4add01(4,5); //9//匿名对象Add()(5,6); //11return 0;
}

【小结】:

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

2. 谓词

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

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

如:

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

示例:

#include <iostream>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 <algorithm>

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 <iostream>
using namespace std;
void fun01()
{/*
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>//取反仿函数*/int num01 = plus<int>()(1,5);cout << num01 << endl;      //6plus<int> pl;int num02 = pl(2,6);cout << num02 << endl;      //8cout << minus<double>()(5,1) << endl;   //4cout << multiplies<double>()(5,2) << endl;  //10cout << divides<int>()(5,2) << endl;    //2cout << modulus<int>()(5,2) << endl;    //1cout << negate<int>()(5) << endl;       //-5cout << 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<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>//小于等于*/cout << equal_to<int>()(10,10) << endl;     //1cout << equal_to<int>()(10,1) << endl;      //0 cout << not_equal_to<int>()(10,1) << endl;  //1cout << greater<int>()(10,1) << endl;       //1cout << greater_equal<int>()(10,1) << endl; //1cout << greater_equal<int>()(10,10) << endl;    //1cout << greater_equal<int>()(10,11) << endl;    //0cout << less<int>()(10,1) << endl;              //0cout << less_equal<int>()(10,11) << endl;       //1
}

示例2:应用于比较

#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
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>,并进行参数萃取

  • 参数萃取:
    • 模板中第一个类型 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<int, bool> 的函数对象类

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);//查找30vector<int>::iterator it = find(nums.begin(),nums.end(),30);cout << (*it) << endl;//查找大于30vector<int>::iterator it02 = find_if(nums.begin(),nums.end(),bind2nd(greater<int>(),30));cout << (*it02) << endl;//查找小于30vector<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 <iostream>
#include <vector>
#include <algorithm>
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 <algorithm>

5.1 遍历

5.1.2 for_caeh

语法:

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

示例1:遍历普通类型

#include <iostream>
#include <vector>
#include <algorithm>
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 50int 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 <iostream>
#include <vector>
#include <algorithm>
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个位置填充10fill(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<int> s;
//    vector<int>::iterator it1 = ns1.begin();
//    for(;it1 != ns1.end();it1++)
//    {
//        vector<int>::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 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/602259.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSON的一些资源

以下是一些推荐的学习资源&#xff1a; 1. **官方网站**: - JSON.org: 这是一个很好的起点&#xff0c;它提供了JSON的基本介绍和语法规则。 2. **在线教程和课程**: - CSDN全方面学习各种资源。 - W3Schools (w3schools.com): 提供了一个关于JSON的教程&#xff0c;涵…

zookeeper经典应用场景之分布式锁

1. 什么是分布式锁 在单体的应用开发场景中涉及并发同步的时候&#xff0c;大家往往采用Synchronized&#xff08;同步&#xff09;或者其他同一个JVM内Lock机制来解决多线程间的同步问题。在分布式集群工作的开发场景中&#xff0c;就需要一种更加高级的锁机制来处理跨机器的进…

MiniTab的宏基础知识

什么是宏&#xff1f; 宏是包含一系列 Minitab 会话命令的文本文件。可以使用宏自动执行重复性任务&#xff08;例如&#xff0c;生成月度报表&#xff09;或扩展 Minitab 的功能&#xff08;例如&#xff0c;计算特殊检验统计量&#xff09;。 Minitab 提供以下类型的宏&…

MongoDB索引详解

概述 索引是一种用来快速查询数据的数据结构。BTree 就是一种常用的数据库索引数据结构&#xff0c;MongoDB 采用 BTree 做索引&#xff0c;索引创建 colletions 上。MongoDB 不使用索引的查询&#xff0c;先扫描所有的文档&#xff0c;再匹配符合条件的文档。使用索引的查询&…

axios post YII2无法接收post参数问题解决

axios post YII2无法接收post参数问题解决 在yii 配置文件中增加 ‘parsers’ > [“application/json” > “yii\web\JsonParser”] 如下所示&#xff1a; $config [id > basic,language > zh-CN,timeZone > env(TIME_ZONE, PRC),basePath > $basePath,bo…

Spring IOC的四种手动注入方法

手动注入 1.Set方法注入-五种类型的注入1.1 业务对象JavaBean第一步&#xff1a;创建dao包下的UserDao类第二步&#xff1a;属性字段提供set⽅法第三步&#xff1a;配置⽂件的bean标签设置property标签第四步&#xff1a;测试 1.2 常用对象String&#xff08;日期类型&#xff…

Adobe Photoshop 快捷键

PS快捷键 图层 选择图层 Ctrl T&#xff1a;可以对图层的大小和位置进行调整 填充图层 MAC: AltBackspace (前景) or CtrlBackspace (背景) WINDOWS: AltDelete (前景) or CtrlDelete (背景) 快速将图层填充为前景色或背景色 平面化图层&#xff08;盖印图层&#xff09…

每日一题——LeetCode1089.复写0

方法一 splice&#xff1a; 通过数组的slice方法&#xff0c;碰到 0就在后面加一个0&#xff0c;最后截取原数组的长度&#xff0c;舍弃后面部分。 但这样做是违反了题目的要求&#xff0c;不要在超过该数组长度的位置写入元素。 var duplicateZeros function(arr) {var le…

软件测试|全面解析Docker Start/Stop/Restart命令:管理容器生命周期的必备工具

简介 Docker是一种流行的容器化平台&#xff0c;用于构建、分发和运行应用程序。在使用Docker时&#xff0c;经常需要管理容器的生命周期&#xff0c;包括启动、停止和重启容器。本文将详细介绍Docker中的docker start、docker stop和docker restart命令&#xff0c;帮助您全面…

Python条形图热图直方图可视化精神健康状态(医学数据集)

目标是比开源精神疾病提供的基本报告更深入地挖掘&#xff0c;并了解更多属性之间的相互作用&#xff0c;这可以为所描述的决策者提供信息。 考虑的问题点&#xff1a; 不同性别属性的员工心理健康是否存在显着差异&#xff1f;不同年龄属性的员工心理健康是否存在显着差异&a…

Go语言程序设计-第7章--接口

Go语言程序设计-第7章–接口 接口类型是对其他类型行为的概括与抽象。 Go 语言的接口的独特之处在于它是隐式实现。对于一个具体的类型&#xff0c;无须声明它实现了哪些接口&#xff0c;只要提供接口所必须实现的方法即可。 7.1 接口即约定 7.2 接口类型 package iotype …

计算机组成原理-进位计数制(进制表示 进制转换 真值和机器树)

文章目录 现代计算机的结构总览最古老的计数方法十进制计数法推广&#xff1a;r进制计数法任意进制->十进制二进制<--->八进制&#xff0c;十六进制 各种进制常见的书写方式十进制->任意进制整数部分小数部分 十进制->二进制&#xff08;拼凑法&#xff09;真值…

Oracle OCP怎么样线上考试呢

大家好&#xff01;今天咱们就来聊聊Oracle OCP这个让人又爱又恨的认证。为啥说又爱又恨呢&#xff1f;因为它既是IT界的“金字招牌”&#xff0c;又是一块硬骨头&#xff0c;不是那么容易啃下来的。好了&#xff0c;废话不多说&#xff0c;我们直奔主题&#xff0c;来看看关于…

解决vue3中watch 监听不到旧值的问题,亲测有效!

问题描述 这个问题是我在公司vue3项目的时候发现的一个问题&#xff0c;watch 在监听对象/数组变量的变化时&#xff0c;发现对象的数据变化时 旧数据 获取到的和新数据是一样的 类似于下面这样 const objref({a:我是原来的值,b:6, })obj.a改变值watch(obj,(nel,old)>{ c…

studio3T mongodb 根据查询条件更新字段 或 删除数据

1. mongodb 等于、不等于$ne、不包含 $nin 以及批量更新数据的使用。 业务场景&#xff1a; 在集合中&#xff0c;根据查询条件&#xff0c;更新数据状态。 实现代码&#xff1a; 1. 部门名称为XXX、状态不等于“完好”的、并且不包含这些编码的数据先查询出来2. 再把状态更…

rust sqlx包(数据库相关)使用方法+问题解决

可以操作pgsql、mysql、mssql、sqlite 异步的&#xff0c;性能应该不错&#xff0c;具体使用有几个坑 除了sqlx库&#xff0c;还有对于具体数据库的库&#xff0c;比如postgres库 演示以pgsql为例&#xff0c;更新时间2024.1.6 官方github: sqlx github rust官方文档&#xff1…

【Python学习】Python学习4-运算符

目录 【Python学习】Python学习4-运算符 前言算术运算符比较&#xff08;关系&#xff09;运算符赋值运算符逻辑运算符位运算符成员运算符身份运算符运算符优先级参考 文章所属专区 Python学习 前言 本章节主要说明Python的运算符。主要有 算术运算符 比较&#xff08;关系&…

强化学习3——马尔可夫性质、马尔科夫决策、状态转移矩阵和回报与策略(上)

与多臂老虎机问题不同&#xff0c;马尔可夫决策过程包含状态信息以及状态之间的转移机制。如果要用强化学习去解决一个实际问题&#xff0c;第一步要做的事情就是把这个实际问题抽象为一个马尔可夫决策过程。 马尔可夫决策过程描述 马尔可夫决策过程以智能体在与环境交互的过…

【linux笔记1】

目录 【linux笔记1】文件内容的理解用户管理用户管理命令添加用户切换用户修改用户信息删除用户 用户组 【linux笔记1】 文件内容的理解 etc文件夹&#xff1a;etc是拉丁语"et cetera"的缩写&#xff0c;意思是“和其他的”或“等等”。在linux系统中&#xff0c;“…

[嵌入式C][入门篇] 快速掌握基础2 (数据类型、常量、变量)

开发环境&#xff1a; 网页版&#xff1a;跳转本地开发(Vscode)&#xff1a;跳转 文章目录 一、基本变量大小和范围&#xff08;1&#xff09;在8位/32位单⽚机中&#xff1a;测试代码结果&#xff1a;64位机器结果&#xff1a;32位机器&#xff08;单片机&#xff09;无对齐限…