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,表示询问个数 ...
随机推荐
- XSS 跨站脚本攻击之构造剖析(一)
1.XSS-Filter:跨站脚本过滤器,用于分析用户提交的输入,并消除潜在的跨站脚本攻击 (1)XSS Filter实际上是一段精心编写的过滤函数作用是过滤XSS跨站脚本代码: (2)绕过XSS F ...
- BZOJ 3932 [CQOI2015]任务查询系统 ——可持久化线段树
[题目分析] 主席树,维护区间大小以及权值之和. 但是细节确实要琢磨很久,WA了几次. [代码] #include <cstdio> #include <cstring> #i ...
- jdbc 各驱动写法
1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); ...
- JavaScrip实现3D旋转动态效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 疯狂java学习笔记之面向对象(八) - static和final
一.static: 1.static是一个标识符: - 有static修饰的成员表明该成员是属于类的; - 没有static修饰的成员表明该成员是属于实例/对象的. 2.static修饰的成员(Fie ...
- [转]走向视网膜(Retina)的Web时代
转载出处:http://www.w3cplus.com/css/towards-retina-web.html 维基百科将Retina译为“视网膜”."Retina"一词,原意是“ ...
- django 后台管理
修改 admin.py from myapp.models import * from django.contrib import admin # Register your models here. ...
- HDU1518 Square(DFS,剪枝是关键呀)
Square Time Limit : 10000/5000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submi ...
- [Sdoi2014]旅行 题解
题目大意: 给出一个n个点的数,和m次操作.每个点有颜色和权值. 每次操作分4种 1:修改一个点的颜色 2:修改一个点的权值 3:询问从x到y的路径上,和x相同颜色的点的权值和(保证x,y同颜色) 4 ...
- Android LruCache(Picasso内存缓存)
Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部,当cache已满的时候加入新的item时,在队列尾部的item会被回收. 如果你cache的某个值需要 ...