标签:c++ 提高4 map容器 共性机制 使用时机 比较| stl算法 算法基础仿函数 谓词 函数适配器 遍历算法
【本文谢绝转载】
《大纲》 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++$
本文出自 “魂斗罗” 博客,谢绝转载!
c++ 提高4 map容器 共性机制 使用时机 比较| STL算法 算法基础仿函数 谓词 函数适配器 遍历算法
标签:c++ 提高4 map容器 共性机制 使用时机 比较| stl算法 算法基础仿函数 谓词 函数适配器 遍历算法
原文地址:http://990487026.blog.51cto.com/10133282/1828046