【本文谢绝转载】
《大纲》
STL
容器
map 容器的4中初始化 遍历
map容器 元素的删除观测map.insert返回值,方法123,已存在就报错,初始化方法4会覆盖
map的查找,异常处理
map容器的range返回两个迭代器
multimap案例,按照部门_增删员工信息
容器共性机制
把对象放到容器中,会自动执行拷贝构造函数
各个容器的使用时机
vector与deque的比较:
算法
算法基础
函数对象(仿函数)
函数对象 与普通函数的区别:-- 相同之处
函数对象 与普通函数的区别:-- 不同之处
分清楚STL算法返回值,是迭代器还是函数对象,是STL算法入门的标志
一元谓词函数 案例,查找能够4整除的数
二元对象,二元谓词 案例
二元函数 二元谓词的应用
二元函数 二元谓词在 集合中的应用 -- find函数默认不支持忽略大小写
二元函数 二元谓词在 集合中的应用 -- 让find函数支持忽略大小写
预定义函数对象 与 函数适配器
函数适配器综合案例 统计大于8的元素个数,预定于与谓词 band2nd 与 not
遍历算法:
1 容器的遍历1 迭代器
2 容器的遍历 自定义函数
3 容器的遍历 仿函数
transform 使用回调函数修改自己的容器
transform 使用预定义函数修改自己的容器
使用函数适配器 与 函数对象
利用transform ,使用适配器,将计算结果储存到list容器
直接将结果输出到屏幕
transform 与 for_each比较
map 容器的4中初始化 遍历
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map>
#include <string>
int main()
{
map <int,string> map1;
//方法1
map1.insert(pair <int,string>(1,"Linux"));
map1.insert(pair <int,string>(2,"Mac"));
//方法2
map1.insert(make_pair(3,"debian"));
map1.insert(make_pair(4,"ubuntu"));
//方法3
map1.insert(map<int ,string>::value_type(5,"redhat"));
map1.insert(map<int ,string>::value_type(6,"centos"));
//方法4
map1[7] = "VIM";
map1[8] = "tcpdump";
map1[8] = "ssh"; //会覆盖tcpdump的值
//遍历
for(map<int,string>::iterator it = map1.begin();it!= map1.end();it++)
{
//map会返回两个元素
cout << it->first << "\t" << it->second << endl;
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
1 Linux
2 Mac
3 debian
4 ubuntu
5 redhat
6 centos
7 VIM
8 ssh
chunli@http://990487026.blog.51cto.com~/c++$
map容器 元素的删除
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map>
#include <string>
int main()
{
map <int,string> map1;
//方法1
map1.insert(pair <int,string>(1,"Linux"));
map1.insert(pair <int,string>(2,"Mac"));
//方法2
map1.insert(make_pair(3,"debian"));
map1.insert(make_pair(4,"ubuntu"));
//方法3
map1.insert(map<int ,string>::value_type(5,"redhat"));
map1.insert(map<int ,string>::value_type(6,"centos"));
//方法4
map1[7] = "VIM";
map1[8] = "tcpdump";
map1[8] = "ssh"; //会覆盖tcpdump的值
//遍历
for(map<int,string>::iterator it = map1.begin();it!= map1.end();it++)
{
//map会返回两个元素
cout << it->first << "\t" << it->second << endl;
}
//容器元素的删除
while(!map1.empty())
{
map<int,string>::iterator it = map1.begin();
//cout << it->first << "\t" << it->second << endl;
map1.erase(it);
}
//容器元素删除的检查
while(!map1.empty())
{
map<int,string>::iterator it = map1.begin();
cout << it->first << "\t" << it->second << endl;
//map1.erase(it);
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
1 Linux
2 Mac
3 debian
4 ubuntu
5 redhat
6 centos
7 VIM
8 ssh
chunli@http://990487026.blog.51cto.com~/c++$
观测map.insert返回值,方法123,已存在就报错,方法4会覆盖
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map>
#include <string>
int main()
{
map <int,string> map1;
//方法1
pair<map<int,string>::iterator,bool> mypair1 = map1.insert(pair <int,string>(1,"Linux"));
map1.insert(pair <int,string>(2,"Mac"));
//方法2
pair<map<int,string>::iterator,bool> mypair2 = map1.insert(make_pair(3,"debian"));
map1.insert(make_pair(4,"ubuntu"));
//方法3
pair<map<int,string>::iterator,bool> mypair5 = map1.insert(map<int ,string>::value_type(5,"redhat"));
if(mypair5.second == true)
{
cout << "插入成功\t" << mypair5.first->first << "\t" << mypair5.first->second << endl;
}
else
{
cout << "5 插入失败\n";
}
pair<map<int,string>::iterator,bool> mypair6 = map1.insert(map<int ,string>::value_type(5,"redhat"));
if(mypair6.second == true)
{
cout << "插入成功\t" << mypair6.first->first << "\t" << mypair6.first->second << endl;
}
else
{
cout << "6 插入失败\n";
}
//方法4
map1[7] = "VIM";
map1[8] = "tcpdump";
map1[8] = "ssh"; //会覆盖tcpdump的值
//遍历
for(map<int,string>::iterator it = map1.begin();it!= map1.end();it++)
{
//map会返回两个元素
cout << it->first << "\t" << it->second << endl;
}
//容器元素的删除
while(!map1.empty())
{
map<int,string>::iterator it = map1.begin();
//cout << it->first << "\t" << it->second << endl;
map1.erase(it);
}
//容器元素删除的检查
while(!map1.empty())
{
map<int,string>::iterator it = map1.begin();
cout << it->first << "\t" << it->second << endl;
//map1.erase(it);
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
插入成功 5 redhat
6 插入失败
1 Linux
2 Mac
3 debian
4 ubuntu
5 redhat
7 VIM
8 ssh
chunli@http://990487026.blog.51cto.com~/c++$
map的查找,异常处理
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map>
#include <string>
int main()
{
map <int,string> map1;
map1[7] = "VIM";
map1[8] = "tcpdump";
map <int ,string> ::iterator it = map1.find(7);
if(it == map1.end())
{
cout << "没有找到" << endl;;
}
else
{
cout << it->first <<"\t" << it->second << endl;
}
map <int ,string> ::iterator it2 = map1.find(99);
if(it2 == map1.end())
{
cout << "没有找到" << endl;;
}
else
{
cout << it2->first <<"\t" << it2->second << endl;
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
7 VIM
没有找到
chunli@http://990487026.blog.51cto.com~/c++$
map容器的range返回两个迭代器
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map>
#include <string>
int main()
{
map <int,string> map1;
map1[6] = "Kernel";
map1[7] = "VIM";
map1[8] = "tcpdump";
map1[9] = "systemd";
pair<map<int,string>::iterator, map<int,string>::iterator> mapair1 = map1.equal_range(7);//返回两个迭代器的位置
//第一个迭代器的位置 >=5
//第二个迭代器的位置 >5
if(mapair1.first == map1.end())
{
cout << "第一个位置不存在\n";
}
else
{
cout << mapair1.first->first << "\t" << mapair1.first->second << endl;
}
if(mapair1.second == map1.end())
{
cout << "第二个位置不存在\n";
}
else
{
cout << mapair1.second->first << "\t" << mapair1.second->second << endl;
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
7 VIM
8 tcpdump
chunli@http://990487026.blog.51cto.com~/c++$
multimap案例,按照部门_增删员工信息
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map>
#include <string>
class Person
{
public:
string name;
int age;
int tel;
double saly;
};
int main()
{
Person p1; p1.name = "斯坦福"; p1.age = 11; p1.saly = 1.1;
Person p2; p2.name = "麻省理工"; p2.age = 21; p2.saly = 2.1;
Person p3; p3.name = "耶鲁"; p3.age = 31; p3.saly = 3.1;
Person p4; p4.name = "剑桥"; p4.age = 41; p4.saly = 4.1;
Person p5; p5.name = "清华"; p5.age = 51; p5.saly = 5.1;
multimap <string,Person> map2;
//sale部门
map2.insert(make_pair("sale",p1));
map2.insert(make_pair("sale",p2));
//研发部
map2.insert(make_pair("development",p3));
map2.insert(make_pair("development",p4));
//财务部
map2.insert(make_pair("financial",p5));
//全部遍历
for(multimap<string,Person>::iterator it = map2.begin();it!=map2.end();it++)
{
cout << it->first << "\t"<< it->second.name << "\t" << it->second.saly << endl;
}
cout << "全部遍历结束\n\n\n\n";
cout << "development部门人数:" << map2.count("development") << endl;
multimap<string,Person>::iterator it2 = map2.find("development");
int num = map2.count("development");
int tag = 0;
while (it2 != map2.end() && tag < num)
{
cout << it2->first << "\t"<< it2->second.name << "\t" << it2->second.saly << endl;
it2++;
tag++;
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
development 耶鲁 3.1
development 剑桥 4.1
financial 清华 5.1
sale 斯坦福 1.1
sale 麻省理工 2.1
全部遍历结束
development部门人数:2
development 耶鲁 3.1
development 剑桥 4.1
chunli@http://990487026.blog.51cto.com~/c++$
容器共性机制
1)基本数据类型值拷贝,而不是引用
2)默认构造函数值拷贝,而不是引用
容器的值的寓意:
理论提高:所有容器提供的都是值(value)语意,而非引用(reference)语意。容器执行插入元素的操作时,内部实施拷贝动作。所以STL容器内存储的元素必须能够被拷贝(必须提供拷贝构造函数)。
除了queue与stack外,每个容器都提供可返回迭代器的函数,运用返回的迭代器就可以访问元素。
通常STL不会丢出异常。要求使用者确保传入正确的参数。
每个容器都提供了一个默认构造函数跟一个默认拷贝构造函数。
如已有容器vecIntA。
vector<int> vecIntB(vecIntA); //调用拷贝构造函数,复制vecIntA到vecIntB中。
与大小相关的操作方法(c代表容器):
c.size(); //返回容器中元素的个数
c.empty(); //判断容器是否为空
比较操作(c1,c2代表容器):
c1 == c2 判断c1是否等于c2
c1 != c2 判断c1是否不等于c2
c1 = c2 把c2的所有元素指派给c1
把对象放到容器中,会自动执行拷贝构造函数
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <vector>
class Teacher
{
public:
Teacher(const char *name,int age)
{
cout << "执行构造函数\n";
m_name = new char [strlen(name) + 1];
strcpy(m_name,name);
m_age = age;
}
Teacher(const Teacher &obj)
{
cout << "执行拷贝构造函数\n";
m_name = new char[strlen(obj.m_name) +1];
strcpy(m_name,obj.m_name);
m_age = obj.m_age;
}
~Teacher()
{
if(m_name != NULL)
{
cout << "执行析构函数 name=" << m_name << endl;
delete [] m_name;
m_name = NULL;
m_age = 0;
}
}
//重载=号操作符
Teacher & operator=(const Teacher &obj)
{
if(m_name != NULL)
{
delete [] m_name;
m_name = NULL;
m_age = 0;
}
m_name = new char[strlen(obj.m_name) +1];
strcpy(m_name,obj.m_name);
m_age = obj.m_age;
return *this;
}
public:
char *m_name;
int m_age;
};
int main()
{
Teacher t1("Linux",32);
vector<Teacher> v1;
v1.push_back(t1); //会调用拷贝构造函数,深拷贝,浅拷贝问题
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
执行构造函数
执行拷贝构造函数
执行析构函数 name=Linux
执行析构函数 name=Linux
chunli@http://990487026.blog.51cto.com~/c++$
各个容器的使用时机
Vector的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描述。
deque的使用场景:比如排队购票系统,对排队者的存储可以采用deque,支持头端的快速移除,尾端的快速添加。如果采用vector,则头端移除时,会移动大量的数据,速度慢。
list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。
set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是vector容器,最坏的情况下可能要遍历完整个容器才能找到该用户。
vector与deque的比较
一:vector.at()比deque.at()效率高,比如vector.at(0)是固定的,deque的开始位置却是不固定的。
二:如果有大量释放操作的话,vector花的时间更少,这跟二者的内部实现有关。
三:deque支持头部的快速插入与快速移除,这是deque的优点。
---------------------------------------------------------------------------------------------------------------------------
STL算法
1,算法基础:
函数对象
是不是很像函数调用啊,所以又叫做仿函数
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//函数对象 -- 仿函数
template <typename T>
class ShowElemt
{
public:
void operator()(T &t)
{
cout <<t <<endl;
}
};
int main()
{
int a = 10;
ShowElemt<int> showElemt;
showElemt(a);
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
10
chunli@http://990487026.blog.51cto.com~/c++$
函数对象 与普通函数的区别: 1,相同之处
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//函数对象 -- 仿函数
template <typename T>
class ShowElemt
{
public:
void operator()(T &t)//重载括号,使用起来更像函数
{
cout <<t <<endl;
}
};
//函数模板
template <typename T>
void FunShowElemt(T &t)
{
cout << t << endl;
}
//普通函数
void FunShowElemt(int &t)
{
cout << t << endl;
}
int main()
{
int a = 10;
ShowElemt<int> showElemt;
showElemt(a); //函数对象的执行,很像一个函数---仿函数
FunShowElemt<int>(a); //函数模板
FunShowElemt(a); //普通函数的调用
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
10
10
10
chunli@http://990487026.blog.51cto.com~/c++$
不同之处
for_each 算法
分清楚STL算法返回值,是迭代器还是函数对象,是STL算法入门的标志
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//函数对象 -- 仿函数
template <typename T>
class ShowElemt
{
public:
ShowElemt()
{
n = 0;
}
void operator()(T &t) //重载括号,使用起来更像函数
{
n++; //记录函数运行次数
cout <<t<< endl;
}
void print()
{
cout << "函数对象的运行次数为"<< n << endl;
}
private:
int n;
};
//函数模板
template <typename T>
void FunShowElemt(T &t)
{
cout << t << endl;
}
//普通函数
void FunShowElemt2(int &t)
{
cout << t << endl;
}
int main()
{
// int a = 10;
// ShowElemt<int> showElemt;
// showElemt(a); //函数对象的执行,很像一个函数---仿函数
// FunShowElemt<int>(a); //函数模板
// FunShowElemt(a); //普通函数的调用
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
//遍历容器
for_each(v1.begin(),v1.end(),ShowElemt<int>() ); //匿名的函数对象
cout << endl;
//普通函数做回调函数
for_each(v1.begin(),v1.end(),FunShowElemt2 );
cout << endl;
//函数对象做函数参数
ShowElemt<int> show1;
//for_each(v1.begin(),v1.end(),show1);
show1 = for_each(v1.begin(),v1.end(),show1);
//for_each算法是值传递,不是引用传递
//所以在for_each算法内部的数据 与外界不发生任何关系,导致函数对象的数值与外界不关联
//用函数对象 接 for_each的返回值
show1.print();
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
1
3
5
1
3
5
1
3
5
函数对象的运行次数为3
chunli@http://990487026.blog.51cto.com~/c++$
一元谓词函数 案例,查找能够4整除的数
find_if返回的是一个迭代器
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//函数对象 -- 仿函数
template <typename T>
class Isdiv
{
public:
Isdiv(const T &divisor)
{
this->divisor = divisor;
}
bool operator()(T &t)
{
return (t%divisor == 0);
}
private:
T divisor;
};
int main()
{
vector<int> v1;
for(int i =9;i<33;i++)
{
v1.push_back(i); //从9开始压入容器
}
int a =4;
Isdiv<int> myDiv(4);
//方法1
find_if(v1.begin(),v1.end(),myDiv);
//方法2
vector<int>::iterator it; //因为返回的是一个迭代器
it = find_if(v1.begin(),v1.end(),Isdiv<int>(a));
if(it == v1.end())
{
cout << "容器中没有能被4整除的元素\n";
}
else
{
cout << "第一个能被4整除的元素是" << *it << endl;
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
第一个能被4整除的元素是12
chunli@http://990487026.blog.51cto.com~/c++$
二元对象,二元谓词 案例
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//函数对象 -- 仿函数
template <typename T>
class Sumadd
{
public:
T operator()(T t1, T t2)
{
return t1 + t2;
}
};
int main()
{
vector<int> v1;
vector<int> v2;
vector<int> v3;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v2.push_back(4);
v2.push_back(5);
v2.push_back(6);
v3.resize(v1.size());
transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),Sumadd<int>() );
for(vector<int>::iterator it=v3.begin();it != v3.end();it++)
{
cout << *it << endl;
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
5
7
9
chunli@http://990487026.blog.51cto.com~/c++$
二元函数 二元谓词的应用
chunli@http://990487026.blog.51cto.com~/c++$
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//二元函数 二元谓词
void show(int &t)
{
cout << t << " ";
}
bool compare(const int &a,const int &b)
{
return a < b;
}
int main()
{
vector<int> v1(10);
//遍历
for(int i=0;i<10;i++)
{
int tmp = rand()%100;
v1[i] = tmp;
}
for(vector<int>::iterator it=v1.begin();it!=v1.end();it++)
{
cout << *it << " ";
}
cout << endl;
//排序
sort(v1.begin(),v1.end(),compare);
//遍历
for_each(v1.begin(),v1.end(),show);
cout << endl;
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
83 86 77 15 93 35 86 92 49 21
15 21 35 49 77 83 86 86 92 93
chunli@http://990487026.blog.51cto.com~/c++$
二元函数 二元谓词在 集合中的应用
1,find函数默认不支持忽略大小写
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
int main()
{
set<string> set1;
set1.insert("aaa");
set1.insert("bbb");
set1.insert("ccc");
set<string>::iterator it = set1.find("aaa");
if(it == set1.end())
{
cout << "没有找到 \n";
}
else
{
cout << "找到了\n";
}
it = set1.find("aAa");
if(it == set1.end())
{
cout << "没有找到 \n";
}
else
{
cout << "找到了\n";
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
找到了
没有找到
chunli@http://990487026.blog.51cto.com~/c++$
二元函数 二元谓词在 集合中的应用
1,让find函数支持忽略大小写
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
//仿函数
struct CompareNoCase
{
bool operator()(const string &str1,const string &str2)
{
//cout << str1 << "\t" << str2 << endl;
string str1_;
str1_.resize(str1.size());
transform(str1.begin(),str1.end(),str1_.begin(),::tolower); //tolower是STL预定义的
string str2_;
str2_.resize(str2.size());
transform(str2.begin(),str2.end(),str2_.begin(),::tolower); //tolower是STL预定义的
//cout << str1_ << "\t" << str2_ << endl;
return (str1_ < str2_);
}
};
int main()
{
set<string> set1;
set1.insert("aaa");
set1.insert("bbb");
set1.insert("ccc");
set<string>::iterator it = set1.find("aAa");
if(it == set1.end())
{
cout << "没有找到 \n";
}
else
{
cout << "找到了\n";
}
//////////////////////////////////////////////////////////////
set<string,CompareNoCase> set2;
set2.insert("aaa");
set2.insert("bbb");
set2.insert("ccc");
set<string,CompareNoCase>::iterator it2 = set2.find("aAa");
if(it2 == set2.end())
{
cout << "没有找到 \n";
}
else
{
cout << "找到了\n";
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
没有找到
找到了
chunli@http://990487026.blog.51cto.com~/c++$
预定义函数对象 与 函数适配器
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
int main()
{
//预定义好的函数对象,能实现不同数据类型的运算
//实现了数据类型 与 算法 的分离
plus<int> intadd;
int a = 10;
int b = 20;
int c = intadd(a,b);
cout << c << endl;
plus<string> stradd;
string s1 = "Hello ";
string s2 = "Linux!";
string s3 = stradd(s1,s2);
cout << s3 << endl;
cout << endl;
vector<string> v1;
v1.push_back("AAA");
v1.push_back("BBB");
v1.push_back("CCC");
v1.push_back("CCC");
v1.push_back("CCC");
sort(v1.begin(),v1.end(),greater<string>() ); //从大到小 排序
for(vector<string>::iterator it = v1.begin();it!=v1.end();it++)
{
cout << *it << " ";
}
cout << endl;
//函数适配器 -- 求CCC出现的次数
string sc = "CCC";
//bind2nd 函数适配器,把预定义函数对象 与 第二个函数的参数绑定
int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(),sc) );
cout << num << "\n";
return 0;
}
/*
如何知道plus<int> 需要两个参数?
打开调试 gdb run
加断点 (gdb) break main.cpp:18
开始运行 (gdb) run
进入函数 (gdb) step
可以看到 std::plus<int>::operator() (this=0x7fffffffeac2, __x=@0x7fffffffeac4: 10, __y=@0x7fffffffeac8: 20)
at /usr/include/c++/4.8/bits/stl_function.h:144
*/
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
30
Hello Linux!
CCC CCC CCC BBB AAA
3
chunli@http://990487026.blog.51cto.com~/c++$
函数适配器综合案例 统计大于8的元素个数,预定于与谓词 band2nd 与 not
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
struct IsGreat
{
public:
IsGreat(int i)
{
m_num = i;
}
bool operator()(int &num)
{
return (num > m_num);
}
private:
int m_num;
};
int main()
{
vector<int> v1;
for(int i = 0;i<10;i++)
{
v1.push_back(i+1);
}
//遍历
for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
{
cout << *it << " ";
}
cout << endl;
//统计数组容器中元素为3的个数
int num1 = count(v1.begin(),v1.end(),3);
cout <<"元素为3的个数有 " <<num1 << endl;
//通过谓词,统计数组容器中元素大于2的个数
int num2 = count_if(v1.begin(),v1.end(),IsGreat(8));
cout <<"元素大于8的个数有 " <<num2 << endl;
//通过预定义函数,统计数组容器中元素大于2的个数
//greater<int>需要两个参数,左边来自容器中的每一个,右边的需要绑定
int num3 = count_if(v1.begin(),v1.end(),bind2nd(greater<int>(),7) );
cout <<"元素大于7的个数有 " <<num3 << endl;
//求奇数的个数
int num4 = count_if(v1.begin(),v1.end(),bind2nd(modulus<int>(),2) );
cout <<"元素奇数的个数有 " <<num4 << endl;
//求偶数的个数 ,not1 翻转一元预定义函数的正值
int num5 = count_if(v1.begin(),v1.end(),not1(bind2nd(modulus<int>(),2)));
cout <<"元素偶数的个数有 " <<num5 << endl;
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
1 2 3 4 5 6 7 8 9 10
元素为3的个数有 1
元素大于8的个数有 2
元素大于7的个数有 3
元素奇数的个数有 5
元素偶数的个数有 5
chunli@http://990487026.blog.51cto.com~/c++$
2,遍历算法:
1 容器的遍历1 迭代器
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
void print(vector<int> &v)
{
for(vector<int>::iterator it = v.begin();it != v.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
print(v1);
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
1 2 3
chunli@http://990487026.blog.51cto.com~/c++$
2 容器的遍历 自定义函数
chunli@http://990487026.blog.51cto.com~/c++$ cat stl_01.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
void show_vector(int n)
{
cout << n << " ";
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
for_each(v1.begin(),v1.end(),show_vector);//会把左边每一个元素传进来
cout << endl;
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run stl_01.cpp && ./run
1 2 3
chunli@http://990487026.blog.51cto.com~/c++$
3 容器的遍历 仿函数
chunli@http://990487026.blog.51cto.com~/c++$ cat stl_02.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
class Show_Vector
{
public:
void operator()(int &n)
{
cout << n << " ";
}
};
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
for_each(v1.begin(),v1.end(),Show_Vector());//会把左边每一个元素传进来
cout << endl;
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run stl_02.cpp && ./run
1 2 3
chunli@http://990487026.blog.51cto.com~/c++$
transform 使用回调函数修改自己的容器
chunli@http://990487026.blog.51cto.com~/c++$ cat stl_03.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
void print(vector<int> &v)
{
for(vector<int>::iterator it = v.begin();it != v.end();it++)
{
cout << *it << "\t";
}
cout << endl;
}
int increase(int n)
{
return n + 100;
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
print(v1);
transform(v1.begin(),v1.end(),v1.begin(),increase); //使用了回调函数
print(v1);
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run stl_03.cpp && ./run
1 2 3 4 5
101 102 103 104 105
chunli@http://990487026.blog.51cto.com~/c++$
transform 使用预定义函数修改自己的容器
chunli@http://990487026.blog.51cto.com~/c++$ cat stl_03.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
void print(vector<int> &v)
{
for(vector<int>::iterator it = v.begin();it != v.end();it++)
{
cout << *it << "\t";
}
cout << endl;
}
int increase(int n)
{
return n + 100;
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
print(v1);
transform(v1.begin(),v1.end(),v1.begin(),negate<int>());//使用了预定义函数
print(v1);
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run stl_03.cpp && ./run
1 2 3 4 5
-1 -2 -3 -4 -5
chunli@http://990487026.blog.51cto.com~/c++$
使用函数适配器 与 函数对象:
利用transform ,使用适配器,将计算结果储存到list容器
直接将结果输出到屏幕
chunli@http://990487026.blog.51cto.com~/c++$ cat stl_03.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
#include <iterator> //直接将结果输出到屏幕
void print_vector(vector<int> &v)
{
for(vector<int>::iterator it = v.begin();it != v.end();it++)
{
cout << *it << "\t";
}
cout << endl;
}
void print_list(list<int> &l)
{
for(list<int>::iterator it = l.begin();it != l.end();it++)
{
cout << *it << "\t";
}
cout << endl;
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
print_vector(v1);
//利用transform ,使用适配器,将计算结果储存到list容器
list<int> list1; //定义一个list int变量
list1.resize(v1.size());//改变容量
transform(v1.begin(),v1.end(),list1.begin(),bind2nd(multiplies<int>(),10));
print_list(list1); //运算结果已经存储到list1
//直接将结果输出到屏幕
transform(v1.begin(),v1.end(),ostream_iterator<int>(cout,"\t"),negate<int>());
cout << endl;
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run stl_03.cpp && ./run
1 2 3 4 5
10 20 30 40 50
-1 -2 -3 -4 -5
chunli@http://990487026.blog.51cto.com~/c++$
transform 与 for_each比较
chunli@http://990487026.blog.51cto.com~/c++$ cat stl_03.cpp
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>
#include <iterator>
void Show_Vector(int &n)
{
cout << n << "\t";
}
int print_vector(int n)
{
cout << n<< "\t";
return n;
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
for_each(v1.begin(),v1.end(),Show_Vector);
cout << endl;
transform(v1.begin(),v1.end(),v1.begin(),print_vector);
cout << endl;
return 0;
}
/*
1) for+each对函数对象的要求:for_each函数原型:
template<class _InIt,
class _Fn1> inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Func);
2) transform 对 函数对象的要求,transform函数原型:
template<class _InIt,
class _OutIt,
class _Fn1> inline
_OutIt _Transform(_InIt _First, _InIt _Last,
_OutIt _Dest, _Fn1 _Func)
{ // transform [_First, _Last) with _Func
for (; _First != _Last; ++_First, ++_Dest)
*_Dest = _Func(*_First); //解释了 为什么 要有返回值
return (_Dest);
}
*/
//一般情况下:for_each所使用的函数对象,参数是引用,没有返回值
//transform所使用的函数对象,参数一般不使用引用,而是还有返回值
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run stl_03.cpp && ./run
1 3 5
1 3 5
chunli@http://990487026.blog.51cto.com~/c++$
转载于:https://blog.51cto.com/990487026/1828046