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,表示询问个数 ...
随机推荐
- WPF datagrid 动态增加列
DataGrid动态增加列 <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.m ...
- cf 二分图
题目链接:http://vjudge.net/contest/133033#problem/C 题目大意:给你n个点,m条边,将其分成两个集合,集合A是图的一个点覆盖,集合B也是图的一个点覆盖,要求集 ...
- Angular JS 学习之控制器
1.AngularJS控制器 控制AngularJS的应用程序的数据:AngularJS控制器是常规的javaScript对象: 2.AngularJS应用程序被控制器控制,ng-controller ...
- DSP using MATLAB 示例Example3.9
用到的性质 上代码: n = 0:100; x = cos(pi*n/2); k = -100:100; w = (pi/100)*k; % freqency between -pi and +pi ...
- 如何查看经过编码的cookie?
方法1.去在线工具网站(http://tool.oschina.net/encode?type=2)手动复制编码的cookie,转码后查看. 方法2.用火狐浏览器打开网页,如果有历史记录(存在cook ...
- [bzoj2118]墨墨的等式【dijk+堆】
10/30的update:如果是冲着dijk的板子来的,建议看多校联考contest中第二场day2的T2,那边的写法比较优秀... --------------------------------- ...
- AFNetworking 之于 https 认证
写在开头: 本来这篇内容准备写在AFNetworking到底做了什么?(三)中的,但是因为我想在三中完结这个系列,碍于篇幅所限.并且这一块内容独立性比较强,所以单独拎出来,写成一篇. 本文从源码的角度 ...
- 用触发器来实现Oracle的自增长列
1, 添加id列 -- ############################################### -- add ID column for XXXXXXTABLE -- #### ...
- bzoj1006 [HNOI2008]神奇的国度
1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 2304 Solved: 1043 Description ...
- iOS之09-特有语法
1.分类 - Category 1> 基本用途 分类:可以给某个类扩充一些方法(不修改原来的代码) 如何在不改变原来类模型的前提下,给类扩充一些方法? 有2种方式: 继承: 分类(Categot ...