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设计理念_算法的更多相关文章

  1. 5_STL设计理念_迭代器

    他山之石,可以攻玉. http://blog.csdn.net/jxh_123/article/details/30793397?utm_source=tuicool&utm_medium=r ...

  2. ALGO-6_蓝桥杯_算法训练_安慰奶牛

    记: 本题目考的是最小生成数,可使用Kruskal算法 第一次,20分 原因:使用动态数组,有概率报运行错误(大雾= =) 第二次,100分 原因:改用静态数组,一次过 示例代码: #include ...

  3. ALGO-5_蓝桥杯_算法训练_最短路

    记: 一开始没接触过关于最短距离的算法,便开始翻阅关于图的知识, 得知关于最短距离的算法有Dijkstra算法(堆优化暂未看懂),Bellman-Ford算法,Floyd算法,SPFA算法. 由于数据 ...

  4. 数据结构&算法(二)_算法基础之前传(递归、时间复杂度、空间复杂度、二分查找)

    什么是算法: 间而言之算法(Algorithm):一个计算过程,解决问题的方法 递归的两个特点: 调用自身 结束条件 递归示例: def func(x): : print("我的小鲤鱼&qu ...

  5. [solution]腾讯TEG_计算广告组_算法题

    度娘笔试归来,题目实打实的,感觉真心不易,上百号人就抢那么几个坑......只恨自己平时积累太少啊~ 故曝一道鹅厂面试用的算法题(当时我就死在了这题上),来为度娘家攒一下RP~ 题目: 对于长度为N的 ...

  6. Java学习笔记(二十)——Java 散列表_算法内容

    [前面的话] 周末,本来打算找人去玩,结果没找到,所以我只好有学习了. 为什么会学习散列表,因为要使用HashMap?因为在做项目的时候,在服务器和客户端需要传输DTO,而传输的属性是动态增加的,所以 ...

  7. 蓝桥杯_算法训练_ALGO10_集合运算

    这个题实际上思路是比较简单的,但是需要注意细节问题. 思路:读入数组之后进行排序,然后再求交.并.补集. 首先排序:(使用的是冒泡排序) #include<iostream> using ...

  8. 蓝桥杯_算法训练_Torry的困惑(基本型)

    这个题目就是求质数的乘积,在加一个模,思路比较简单,直接上代码: #include<iostream> using namespace std; bool isPrime(int a) { ...

  9. 蓝桥杯_算法训练_区间k大数查询

    问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个包含一个正整数m,表示询问个数 ...

随机推荐

  1. 《DSP using MATLAB》示例Example4.3 双边序列

  2. localhost和127.0.0.1 的区别

  3. redis 的安装

    1: redis 是什么 Redis is an open source (BSD licensed), in-memory data structure store, used as databas ...

  4. flume 使用 spool source的时候字符集出错

    1. 错误所在 -- ::, (pool--thread-) [ERROR - org.apache.flume.source.SpoolDirectorySource$SpoolDirectoryR ...

  5. SPFA(建图) HDOJ 4725 The Shortest Path in Nya Graph

    题目传送门 题意:有两种路径,每个点会分别在某一层,层相邻之间权值c.还有直接两点传送,花费w.问1到n的最短距离. 分析:1~n正常建边.然后n + a[i]表示i点在第a[i]层.然后再优化些就不 ...

  6. iOS学习03C语言循环结构

    1.while循环 while (循环条件) {        循环体: } // 1.定义循环变量 ; // 2.循环条件 ) { // 3.循环体 printf("%d\n", ...

  7. BZOJ4367 : [IOI2014]holiday假期

    设 $fl[i]$表示从$S$向左走,用了不超过$i$天且不回头的最大收益. $fr[i]$表示从$S$向右走,用了不超过$i$天且不回头的最大收益. $gl[i]$表示从$S$向左走,用了不超过$i ...

  8. Jaxb 解析 带有继承关系的bean与xml

    具体方法: 1. 在jaxb的setClasstobebounds中,只需要子类的class,无需父类. 2. 父类的前面加如下声明: @XmlAccessorType(XmlAccessType.F ...

  9. uestc 1073 秋实大哥与线段树 Label:线段树

    秋实大哥与线段树 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) “学习本无底, ...

  10. JS:操作样式表1:行内样式

    //访问元素样式1, stye属性只对行内样式有用 var box = document.getElementById("box"); // alert(box.style.col ...