4_STL设计理念_算法
STL算法,容器,迭代器的设计理念
1.STL容器通过 类模板 技术,实现 数据类型 和 容器模型的分离;
2.迭代器技术 实现了 遍历和操作容器的统一方法
3.STL算法设计理念:通过预定义的函数对象和函数对象实现了数据类型与算法的分离;预定义函数对象处理基本数据类型,函数对象实现了自定义数据类型与算法的分离;
核心思想:函数对象本质是回调函数;
回调函数的思想:实现任务的编写者 和 任务的调用者有效解耦合。
一、STL算法的设计理念
函数对象
一元函数对象、一元谓词
二元函数对象、二元谓词
预定义函数对象
函数适配器
容器算法迭代器的设计理念:
要点:分清楚STL算法返回的值是迭代器 还是 谓词(函数对象)
transform算法的输入,通过迭代器first和last指向的元素作为输入;通过result作为输出;
通过函数对象来做自定义数据类型的运算。
函数对象:重载函数调用操作符的类,其对象常称为函数对象。
他们是行为类似函数的对象,通过:对象名(参数列表)。又称为仿函数,伪函数;
通过重载类的 operator()来实现的。
一元函数对象:函数参数为1个的函数对象
二元函数对象:函数参数为2个
谓词可以是一个仿函数,也可以是一个回调函数
一元谓词 函数参数1个,函数返回值为bool类型
二元谓词 函数参数2个,函数返回值为bool类型
函数对象与普通函数的异同点:
1.调用方式的相似性
template <typename T>
class ShowElement
{
public:
void operator()(T &t) //重载了函数调用操作符的类 定义的对象 叫 函数对象
{
cout << t << " ";
}
protected:
private:
};
template <typename T> //函数模板
void FuncShowElement(T &t)
{
cout << t << endl;
}
void FuncShowElement(int &t) //普通函数
{
cout << t << endl;
}
void main()
{
int a = ;
ShowElement<int>showElement;
showElement(a); //函数对象的()执行,很像一个函数,是一个仿函数 FuncShoeElement<int>(a); //函数模板
FuncShoeElement(a); //普通函数
}
不同点:函数对象的优势:
函数对象是 类对象,能保持调用状态信息
vector<int>v1;
v1.push_back();
v1.push_back();
v1.push_back(); for_each(v1.begin(),v1.end(),ShowElement<int>()); //匿名函数对象 匿名仿函数
for_each(v1.begin(),v1.end(),FuncShowElement); //通过回调函数
for_each算法中 :
函数对象的两种用法:
函数对象做函数参数
函数对象当返回值
for_each算法的 函数对象 是元素 即值传递,不是引用传递。但返回的是一个元素,可以通过返回值记录状态
ShowElement<int>show;
show = for_each(v1.begin(),v1.end(),show);//里面show是实参,左值是返回值
show.printN();
一元谓词和STL算法配合使用
template<typename T>
class isDiv
{
public:
isDiv(const T& divisor) //拷贝构造函数
{
this->divisor = divisor;
}
bool operator()(T& t)
{
return (t % divisor == );
}
protected:
private:
T divisor;
}
void main()
{
vector<int>v2;
for(int i = ; i < ; i++)
{
v2.push_back(i);
}
int a = ;
isDiv<int>myDiv(a);
//find_if(v2.begin(),v2.end(),myDiv);
vector<int>::iterator it;
it = find_if(v2.begin(),v2.end(),isDiv<int>(a));
if(it == v2.end())
{
cout << "容器中没有被4整除的元素" << endl;
}
else
{
cout << "第一个被4整除的元素: " << *it <<endl;
}
}
//查看源码,find_if返回的是迭代器;
二元函数对象,二元谓词:
两个数的比较,加和等;transform();
template<typename T>
class sumAdd
{
public:
T operator()(T t1,T t2)
{
return t1+t2;
}
}
void main()
{
vector<int>v1,v2;
vector<int>v3;
v1.push_back();
v1.push_back();
v1.push_back(); v2.push_back();
v2.push_back();
v2.push_back(); v3.resize();
//前两个参数是一个容器的迭代器参与运算的起点和终点,第三个参数是另一个容器的参与运算的开始位置;
//第四个参数是结果存放的位置(可以是v1),第五个参数是函数对象(自己实现业务功能)
//返回值是 第四个参数,即 存放结果的迭代器
transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),sumAdd<int>());
}
二元谓词:(比较大小)
bool myCompre(const int& a,const int& b)
{
retrun a < b; //从小到大排序
}
void main()
{
vector<int>v();
for(int i = ; i < ; i++)
{
int tmp = rand()%;
v[i] = tmp;
}
sort(v.begin(),v.end(),myCompare);
}
二元谓词在set集合中的应用:
find默认区分大小写,利用二元谓词让其不区分大小写;
struct compareNoCase
{
bool operator()(const string& str1,const string& str2)
{
string str1_;
str1_.resize(str1.size());
transform(str1.begin(),str1,end(),str1_.begin(),tolower);
string str2_;
str2_.resize(str2.size());
transform(str2.begin(),str2.end(),str2_.begin(),tolower)
return (str1_ < str2_);
}
} set<string,compareNoCase>::iterator it = set1.find("aAa");//find函数默认区分大小写
//利用仿函数的set实现了内容全部转化为小写,排序;其内部函数,insert()和find()的()已被重载,都有转化为小写的功能;
预定义函数对象和函数适配器
#include <functional>
plus<int>add; //两个整形数相加
plus<string>add; //字符串连接 sort(v1.begin(),v1.end(),greater<string>());//加谓词后,从大到小排序 //统计出现次数:
//equal_to<string>()有两个参数:left参数来自容器,right参数来自sc
//bind2nd是函数适配器;把预定义函数对象 和 第二个参数进行绑定
string sc = "ccc";
int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(),sc)); //bind1st( , );
函数适配器:
STL中已经定义了大量函数对象,但有时候需要对函数返回值进行进一步简单计算,或者填上多余参数,不能直接代入算法。
函数适配器将一种函数对象转化为另一种符合要求的函数对象。
绑定适配器,组合适配器,指针函数适配器,成员函数适配器。
binder1st:将数值绑定到二元函数的第一个参数,适配成一元函数 //bind1st(op,value)
binder2nd:将数值绑定到二元函数的第二个参数,适配成一元函数 //bind2nd(op,value)
unary_negate:将一元谓词的返回值适配成其逻辑反 //not1(op)
binary_negate:将二元谓词的返回值适配成其逻辑反 //not2(op) int num = count(v1.begin(),v1.end(),); //统计v1中3的个数 //通过 谓词 求大于2的个数
class isGreat
{
public:
isGreat(int i)
{
m_num = i;
}
bool operator()(int& num)
{
if(num > m_num)
return true;
else
return false;
}
private:
int m_num;
};
int num1 = count_if(v1.begin(),v1.end(),isGreat()); //通过预定义函数对象 求大于2的个数
int num2 = count_if(v1.begin(),v1.end(),bind2nd(greater<int>(),)); //求 奇数个数
int num3 = count_if(v1.begin(),v1.end(),bind2nd(modulus<int>(),));
int num4 = count_if(v1.begin(),v1.end(),not1(bind2nd(modulus<int>(),)));
4_STL设计理念_算法的更多相关文章
- 5_STL设计理念_迭代器
他山之石,可以攻玉. http://blog.csdn.net/jxh_123/article/details/30793397?utm_source=tuicool&utm_medium=r ...
- ALGO-6_蓝桥杯_算法训练_安慰奶牛
记: 本题目考的是最小生成数,可使用Kruskal算法 第一次,20分 原因:使用动态数组,有概率报运行错误(大雾= =) 第二次,100分 原因:改用静态数组,一次过 示例代码: #include ...
- ALGO-5_蓝桥杯_算法训练_最短路
记: 一开始没接触过关于最短距离的算法,便开始翻阅关于图的知识, 得知关于最短距离的算法有Dijkstra算法(堆优化暂未看懂),Bellman-Ford算法,Floyd算法,SPFA算法. 由于数据 ...
- 数据结构&算法(二)_算法基础之前传(递归、时间复杂度、空间复杂度、二分查找)
什么是算法: 间而言之算法(Algorithm):一个计算过程,解决问题的方法 递归的两个特点: 调用自身 结束条件 递归示例: def func(x): : print("我的小鲤鱼&qu ...
- [solution]腾讯TEG_计算广告组_算法题
度娘笔试归来,题目实打实的,感觉真心不易,上百号人就抢那么几个坑......只恨自己平时积累太少啊~ 故曝一道鹅厂面试用的算法题(当时我就死在了这题上),来为度娘家攒一下RP~ 题目: 对于长度为N的 ...
- Java学习笔记(二十)——Java 散列表_算法内容
[前面的话] 周末,本来打算找人去玩,结果没找到,所以我只好有学习了. 为什么会学习散列表,因为要使用HashMap?因为在做项目的时候,在服务器和客户端需要传输DTO,而传输的属性是动态增加的,所以 ...
- 蓝桥杯_算法训练_ALGO10_集合运算
这个题实际上思路是比较简单的,但是需要注意细节问题. 思路:读入数组之后进行排序,然后再求交.并.补集. 首先排序:(使用的是冒泡排序) #include<iostream> using ...
- 蓝桥杯_算法训练_Torry的困惑(基本型)
这个题目就是求质数的乘积,在加一个模,思路比较简单,直接上代码: #include<iostream> using namespace std; bool isPrime(int a) { ...
- 蓝桥杯_算法训练_区间k大数查询
问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个包含一个正整数m,表示询问个数 ...
随机推荐
- 《DSP using MATLAB》示例Example4.3 双边序列
- localhost和127.0.0.1 的区别
- redis 的安装
1: redis 是什么 Redis is an open source (BSD licensed), in-memory data structure store, used as databas ...
- flume 使用 spool source的时候字符集出错
1. 错误所在 -- ::, (pool--thread-) [ERROR - org.apache.flume.source.SpoolDirectorySource$SpoolDirectoryR ...
- SPFA(建图) HDOJ 4725 The Shortest Path in Nya Graph
题目传送门 题意:有两种路径,每个点会分别在某一层,层相邻之间权值c.还有直接两点传送,花费w.问1到n的最短距离. 分析:1~n正常建边.然后n + a[i]表示i点在第a[i]层.然后再优化些就不 ...
- iOS学习03C语言循环结构
1.while循环 while (循环条件) { 循环体: } // 1.定义循环变量 ; // 2.循环条件 ) { // 3.循环体 printf("%d\n", ...
- BZOJ4367 : [IOI2014]holiday假期
设 $fl[i]$表示从$S$向左走,用了不超过$i$天且不回头的最大收益. $fr[i]$表示从$S$向右走,用了不超过$i$天且不回头的最大收益. $gl[i]$表示从$S$向左走,用了不超过$i ...
- Jaxb 解析 带有继承关系的bean与xml
具体方法: 1. 在jaxb的setClasstobebounds中,只需要子类的class,无需父类. 2. 父类的前面加如下声明: @XmlAccessorType(XmlAccessType.F ...
- uestc 1073 秋实大哥与线段树 Label:线段树
秋实大哥与线段树 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) “学习本无底, ...
- JS:操作样式表1:行内样式
//访问元素样式1, stye属性只对行内样式有用 var box = document.getElementById("box"); // alert(box.style.col ...