c++提高学习笔记——05-c++STLday12
在学习c++提高-STL总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
05-c++STLday12
目录:
一、上节作业——multimap案例
二、常用算法
1、函数对象
2、谓词
3、内建函数对象
4、适配器使用
5、常用遍历算法
6、常用查找算法
7、常用排序算法
8、常用拷贝和替换算法
9、常用算数生成算法
10、常用集合算法
11、综合案例——学校演讲比赛
三、总结
一、上节作业——multimap案例
//公司今天招聘了5个员工,5名员工进入公司之后,需要指派员工在那个部门工作
//人员信息有: 姓名 年龄 电话 工资等组成
//通过Multimap进行信息的插入 保存 显示
//分部门显示员工信息 显示全部员工信息
代码如下:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<string> 5 #include<vector> 6 #include<map> 7 #include<ctime> 8 /* 9 //公司今天招聘了5个员工,5名员工进入公司之后,需要指派员工在那个部门工作 10 //人员信息有: 姓名 年龄 电话 工资等组成 11 //通过Multimap进行信息的插入 保存 显示 12 //分部门显示员工信息 显示全部员工信息 13 14 */ 15 16 enum{ RENLI, YANFA,MEISHU}; 17 18 class Worker 19 { 20 21 public: 22 string m_Name; 23 int m_Money; 24 }; 25 26 void createWorker(vector<Worker>& v) 27 { 28 string nameSeed = "ABCDE"; 29 for(int i = 0; i < 5; i++) 30 { 31 string name = "员工"; 32 name += nameSeed[i]; 33 34 int money = rand() % 10000 + 10000;//10000~19999 35 36 Worker w; 37 w.m_Name = name; 38 w.m_Money = money; 39 40 v.push_back(w); 41 } 42 43 } 44 45 void setGroup(vector<Worker>& v, multimap<int, Worker>& m) 46 { 47 for(vector<Worker>::iterator it = v.begin(); it != v.end(); it++) 48 { 49 //随机产生部门编号 50 int departmentId = rand() % 3;//0 1 2 51 //将员工分到multimap容器中 52 m.insert(make_pair(departmentId, *it)); 53 } 54 55 } 56 57 void showGroup(multimap<int, Worker>& m) 58 { 59 //人力部门显示 60 cout << "人力部门员工如下:" << endl; 61 62 //0 A B 1 C 2 D E 63 //如果找不到,会报错吗? 64 multimap<int, Worker>::iterator pos = m.find(RENLI); 65 int index = 0; 66 int num = m.count(RENLI); 67 for(; pos != m.end() && index < num; pos++, index++) 68 { 69 cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Money << endl; 70 } 71 72 cout << "------------------" << endl; 73 74 cout << "研发部门员工如下:" << endl; 75 76 //0 A B 1 C 2 D E 77 pos = m.find(YANFA); 78 index = 0; 79 num = m.count(YANFA); 80 for(; pos != m.end() && index < num; pos++, index++) 81 { 82 cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Money << endl; 83 } 84 85 cout << "------------------" << endl; 86 87 cout << "美术部门员工如下:" << endl; 88 89 //0 A B 1 C 2 D E 90 pos = m.find(MEISHU); 91 index = 0; 92 num = m.count(MEISHU); 93 for(; pos != m.end() && index < num; pos++, index++) 94 { 95 cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Money << endl; 96 } 97 98 } 99 100 101 void test01() 102 { 103 //最后添加随机数种子 104 srand((unsigned int)time(NULL)); 105 106 //声明一个存放员工的容器 107 vector<Worker>v; 108 109 //创建5名员工 110 createWorker(v); 111 112 /* 113 //员工创建测试 114 for(vector<Worker>::iterator it = v.begin(); it != v.end(); it++) 115 { 116 cout << "员工姓名:" << it->m_Name << "工资:" << it->m_Money << endl; 117 } 118 */ 119 120 //设置分组 121 //分组的multimap容器 122 multimap<int, Worker>m; 123 setGroup(v, m); 124 125 //分部门显示员工 126 showGroup(m); 127 } 128 129 int main() 130 { 131 test01(); 132 133 system("pause"); 134 return EXIT_SUCCESS; 135 }
二、常用算法
1、函数对象
重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用。
注意:
1.函数对象(仿函数)是一个类,不是一个函数。
2.函数对象(仿函数)重载了”() ”操作符使得它可以像函数一样调用。
分类:假定某个类有一个重载的operator(),而且重载的operator()要求获取一个参数,我们就将这个类称为“一元仿函数”(unary functor);相反,如果重载的operator()要求获取两个参数,就将这个类称为“二元仿函数”(binary functor)。
函数对象的作用主要是什么?STL提供的算法往往都有两个版本,其中一个版本表现出最常用的某种运算,另一版本则允许用户通过template参数的形式来指定所要采取的策略。
总结:
1、函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。
2、函数对象超出普通函数的概念,函数对象可以有自己的状态
3、函数对象可内联编译,性能好。用函数指针几乎不可能
4、模版函数对象使函数对象具有通用性,这也是它的优势之一
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 5 6 class MyPrint 7 { 8 public: 9 void operator()(int num) 10 { 11 cout << "num:" << num << endl; 12 count++; 13 } 14 int count = 0; 15 }; 16 17 void MyPrint2(int num) 18 { 19 cout << "num:" << num << endl; 20 } 21 22 void test01() 23 { 24 //MyPrint是一个类,而不是函数 25 MyPrint myPrint; 26 myPrint(111); 27 28 //MyPrint2(111);//普通函数调用 29 30 MyPrint()(1000);//匿名对象调用 31 32 } 33 34 //函数对象超出普通函数概念,内部可以保存状态 35 void test02() 36 { 37 MyPrint myPrint; 38 myPrint(111); 39 myPrint(111); 40 myPrint(111); 41 myPrint(111); 42 43 cout << "myPrint使用次数:" << myPrint.count << endl; 44 } 45 46 //函数对象作为参数 47 void doPrint(MyPrint print, int num) 48 { 49 print(num); 50 } 51 52 void test03() 53 { 54 doPrint(MyPrint(), 20); 55 } 56 57 int main() 58 { 59 test01(); 60 61 system("pause"); 62 return EXIT_SUCCESS; 63 }
2、谓词
谓词是指普通函数或重载的operator()返回值是bool类型的函数对象(仿函数)。如果operator接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词可作为一个判断式。
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<vector> 5 #include<algorithm> 6 7 class GreaterThan20 8 { 9 public: 10 bool operator()(int val) 11 { 12 return val > 20; 13 } 14 15 16 }; 17 18 19 //一元谓词 20 void test01() 21 { 22 vector<int>v; 23 v.push_back(10); 24 v.push_back(20); 25 v.push_back(30); 26 v.push_back(40); 27 v.push_back(50); 28 29 //查找第一个大于20的数字 30 //第三个参数为:函数对象,匿名对象 31 vecot<int>::iterator pos = find_if(v.begin(), v.end(),GreaterThan20()); 32 if(pos != v.end()) 33 { 34 cout << "找到大于20的数字为:" << *pos << endl; 35 } 36 else 37 { 38 cout << "未找到" << endl; 39 } 40 41 } 42 43 //二元谓词 44 class MyCompare 45 { 46 public: 47 bool operator()(int v1, int v2) 48 { 49 return v1 > v2; 50 } 51 52 }; 53 void test02() 54 { 55 vector<int>v; 56 v.push_back(10); 57 v.push_back(20); 58 v.push_back(30); 59 v.push_back(40); 60 v.push_back(50); 61 62 sort(v.begin(), v.end(), MyCompare()); 63 64 //匿名函数:lambda表达式[](){}; 65 for_each(v.begin(), v.end(), [](int val){ cout << val << " ";}); 66 } 67 68 69 int main() 70 { 71 test01(); 72 73 system("pause"); 74 return EXIT_SUCCESS; 75 }
3、内建函数对象
STL内建了一些函数对象。分为:算数类函数对象,关系运算类函数对象,逻辑运算类仿函数。这些仿函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。使用内建函数对象,需要引入头文件 #include<functional>。
6个算数类函数对象,除了negate是一元运算,其他都是二元运算。
1 template<class T> T plus<T>//加法仿函数 2 template<class T> T minus<T>//减法仿函数 3 template<class T> T multiplies<T>//乘法仿函数 4 template<class T> T divides<T>//除法仿函数 5 template<class T> T modulus<T>//取模仿函数 6 template<class T> T negate<T>//取反仿函数
6个关系运算类函数对象,每一种都是二元运算。
1 template<class T> bool equal_to<T>//等于 2 template<class T> bool not_equal_to<T>//不等于 3 template<class T> bool greater<T>//大于 4 template<class T> bool greater_equal<T>//大于等于 5 template<class T> bool less<T>//小于 6 template<class T> bool less_equal<T>//小于等于
逻辑运算类运算函数,not为一元运算,其余为二元运算。
1 template<class T> bool logical_and<T>//逻辑与 2 template<class T> bool logical_or<T>//逻辑或 3 template<class T> bool logical_not<T>//逻辑非
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 //内建函数对象头文件 5 #include<functional> 6 #include<vector> 7 #include<algorithm> 8 9 void test01() 10 { 11 //template<class T> T negate<T>取反仿函数 12 negate<int>n; 13 14 cout << n(10) << endl; 15 16 //template<class T> T plus<T>加法仿函数 17 plus<int>p; 18 19 cout << p(1, 1) << endl; 20 21 } 22 23 //template<class T> bool greater<T>大于 24 void test02() 25 { 26 vector<int>v; 27 28 v.push_back(10); 29 v.push_back(30); 30 v.push_back(50); 31 v.push_back(20); 32 v.push_back(40); 33 34 sort(v.begin(), v.end(), greater<int>()); 35 36 for_each(v.begin(), v.end(), [](int val){ cout << val << " ";}) 37 38 } 39 40 int main() 41 { 42 test01(); 43 44 system("pause"); 45 return EXIT_SUCCESS; 46 }
4、适配器使用
//函数适配器bind1st bind2nd
//现在我有这个需求 在遍历容器的时候,我希望将容器中的值全部加上100之后显示出来,怎么做?
//我们直接给函数对象绑定参数 编译阶段就会报错
//for_each(v.begin(), v.end(), bind2nd(myprint(),100));
//如果我们想使用绑定适配器,需要我们自己的函数对象继承binary_function 或者 unary_function
//总结: bind1st和bind2nd区别?
//bind1st : 将参数绑定为函数对象的第一个参数
//bind2nd : 将参数绑定为函数对象的第二个参数
//bind1st bind2nd将二元函数对象转为一元函数对象
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<vector> 5 #include<algorithm> 6 #include<functional> 7 #include<string> 8 //函数适配器 9 class Myprint:public binary_function<int, int, void> 10 { 11 public: 12 void operator()(int v, int start) const 13 { 14 //cout << v + start << endl; 15 cout << "v = " << v << " start = " << start << " v + start = "v + start << endl; 16 } 17 18 }; 19 20 void test01() 21 { 22 vector<int>v; 23 for(int i = 0; i < 10; i++) 24 { 25 v.push_back(i); 26 } 27 28 cout << "请输入起始值:" << endl; 29 int num; 30 cin >> num; 31 32 //for_each(v.begin(), v.end(), bin2nd(Myprint(), num));//Myprint()提供仿函数,再更改为适配器绑定 33 for_each(v.begin(), v.end(), bin1st(Myprint(), num)); 34 } 35 //第一步:绑定数据,bind2nd 36 //第二步:继承类:binary_function<参数类型1,参数类型2,返回值类型> 37 //第三步:加const修饰operator() 38 39 40 class GreaterThanFive:public unary_function<int, bool> 41 { 42 public: 43 bool operator()(int v) const 44 { 45 return v > 5; 46 } 47 48 } 49 50 51 //取反适配器 52 void test02() 53 { 54 //一元取反 55 vector<int>v; 56 for(int i = 0; i < 10; i++) 57 { 58 v.push_back(i); 59 } 60 61 //查找大于5的数字 62 //需求改为找小于5的数字 63 //vector<int>::iterator pos = find_if(v.begin(), v.end(), not1(GreaterThanFive())); 64 65 vector<int>::iterator pos = find_if(v.begin(), v.end(), not1(bin2nd(greater<int>(),5))); 66 if(pos != v.end()) 67 { 68 cout << "找到小于5的数字为:" << *pos << endl; 69 } 70 else 71 { 72 cout << "未找到" << endl; 73 } 74 } 75 //一元取反适配器 not1 76 //继承unary_function<参数类型1,返回值类型> 77 //const修饰 78 79 80 void Myprint03(int v) 81 { 82 cout << v + start << endl; 83 } 84 85 //函数指针适配器 86 void test03() 87 { 88 vector<int>v; 89 for(int i = 0; i < 10; i++) 90 { 91 v.push_back(i); 92 } 93 94 //将函数指针 适配为 函数对象 95 //ptr_fun 96 97 for_each(v.begin(), v.end(), bin2nd( ptr_fun(Myprint03) , 100)); 98 } 99 100 101 //成员函数适配器 102 class Person 103 { 104 public: 105 Person(string name, int age) 106 { 107 this->m_Name = name; 108 this->m_Age = age; 109 } 110 111 void showPerson() 112 { 113 cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl; 114 } 115 void plusAge() 116 { 117 this->m_Age = this->m_Age + 100; 118 } 119 120 121 string m_Name; 122 int m_Age; 123 }; 124 125 void MyPrintPerson(Person& p) 126 { 127 cout << "成员函数中:姓名:" << p.m_Name << "年龄:" << p.m_Age << endl; 128 } 129 130 void test04() 131 { 132 vector<Person>v; 133 134 Person p1("aaa", 10); 135 Person p1("bbb", 15); 136 Person p1("ccc", 18); 137 Person p1("ddd", 40); 138 139 v.push_back(p1); 140 v.push_back(p2); 141 v.push_back(p3); 142 v.push_back(p4); 143 144 //成员函数适配器 145 //mem_fun_ref 146 for_each(v.begin(), v.end(), mem_fun_ref(&Person::showPerson)); 147 for_each(v.begin(), v.end(), mem_fun_ref(&Person::plusAge)); 148 for_each(v.begin(), v.end(), mem_fun_ref(&Person::showPerson)); 149 } 150 151 int main() 152 { 153 test01(); 154 155 system("pause"); 156 return EXIT_SUCCESS; 157 }
算法主要是由头文件<algorithm> <functional> <numeric>组成。
<algorithm>是所有STL头文件中最大的一个,其中常用的功能涉及到比较,交换,查找,遍历,复制,修改,反转,排序,合并等...
<numeric>体积很小,只包括在几个序列容器上进行的简单运算的模板函数.
<functional> 定义了一些模板类,用以声明函数对象。
5、常用遍历算法
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<algorithm> 5 #include<vector> 6 #include<functional> 7 8 /* 9 遍历算法 遍历容器元素 10 @param beg 开始迭代器 11 @param end 结束迭代器 12 @param _callback 函数回调或者函数对象 13 @return 函数对象 14 */ 15 16 /* 17 void myPrint(int v) 18 { 19 cout << v << endl; 20 } 21 */ 22 //1.更改为仿函数 23 class myPrint01 24 { 25 public: 26 void operator()(int v) 27 { 28 cout << v << endl; 29 } 30 }; 31 /* 32 //有些书上写的struct 33 struct myPrint01 34 { 35 void operator()(int v) 36 { 37 cout << v << endl; 38 } 39 }; 40 */ 41 42 void test01() 43 { 44 vector<int>v; 45 for(int i = 0; i < 10; i++) 46 { 47 v.push_back(i); 48 } 49 50 //for_each(v.begin(), v.end(), myPrint); 51 for_each(v.begin(), v.end(), myPrint01());//更改为仿函数 52 } 53 54 class myPrint02 55 { 56 public: 57 void operator()(int v) 58 { 59 cout << v << endl; 60 m_Count++; 61 } 62 int m_Count; 63 }; 64 //3.for_each可以有返回值(保存内部记录) 65 void test02() 66 { 67 vector<int>v; 68 for(int i = 0; i < 10; i++) 69 { 70 v.push_back(i); 71 } 72 73 74 myPrint02 print2 = for_each(v.begin(), v.end(), myPrint02()); 75 cout << "Count = " << print2.m_Count << endl; 76 } 77 78 //4.for_each可以绑定参数进行输出 79 struct myPrint03:public binary_function<int, int, void> 80 { 81 void operator()(int v, int start) const 82 { 83 cout << v + start << endl; 84 } 85 }; 86 87 void test03() 88 { 89 vector<int>v; 90 for(int i = 0; i < 10; i++) 91 { 92 v.push_back(i); 93 } 94 95 for_each(v.begin(), v.end(), bind2nd(myPrint03(), 10000)); 96 97 } 98 99 100 101 /* 102 transform算法 将指定容器区间元素搬运到另一容器中 103 注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存 104 @param beg1 源容器开始迭代器 105 @param end1 源容器结束迭代器 106 @param beg2 目标容器开始迭代器 107 @param _cakkback 回调函数或者函数对象 108 @return 返回目标容器迭代器 109 */ 110 111 class TransForm 112 { 113 public: 114 int operator()(int val) 115 { 116 return val + 10; 117 } 118 119 120 }; 121 122 void test04() 123 { 124 vector<int>v;//原容器 125 for(int i = 0; i < 10; i++) 126 { 127 v.push_back(i); 128 } 129 130 vector<int>vTarget;//目标容器 131 //提前开辟内存 132 vTarget.resize(v.size()); 133 134 transform(v.begin(), v.end(), vTarget.begin(), TransForm()); 135 136 for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " ";}); 137 } 138 139 //transform第二种用法:将两个容器数据 相加/相减 搬运到目标容器 140 class TransForm2 141 { 142 public: 143 int operator()(int val1, int val2) 144 { 145 return val1 + val2; 146 } 147 148 149 }; 150 151 void test05() 152 { 153 vector<int>v1; 154 vector<int>v2; 155 for(int i = 0; i < 10; i++) 156 { 157 v1.push_back(100 + i); 158 v2.push_back(200 + i); 159 } 160 vector<int>vTarget;//目标容器 161 vTarget.resize(v1.size()); 162 163 transform(v1.begin(), v1.end(), v2.begain(), vTarget.begin(), TransForm2()); 164 165 //300 302... 166 for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " ";}); 167 } 168 169 170 int main() 171 { 172 test01(); 173 174 system("pause"); 175 return EXIT_SUCCESS; 176 }
6、常用查找算法
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<algorithm> 5 #include<vector> 6 #include<string> 7 #include<functional> 8 9 /* 10 find算法 查找元素 11 @param beg 容器开始迭代器 12 @param end 容器结束迭代器 13 @param value 查找的元素 14 @return 返回查找元素的位置 15 */ 16 17 void test01() 18 { 19 vector<int>v; 20 for(int i = 0; i < 10; i++) 21 { 22 v.push_back(i); 23 } 24 25 vector<int>::iterator pos = find(v.begin(), v.end(), 5); 26 if(pos != v.end()) 27 { 28 cout << "找到了数据:" << *pos << endl; 29 } 30 else 31 { 32 cout << "未找到" << endl; 33 } 34 } 35 36 37 class Person 38 { 39 public: 40 Person(string name, int age) 41 { 42 this->m_Name = name; 43 this->m_Age = age; 44 } 45 46 bool operator==(const Person& p) 47 { 48 if(this->m_Name == p.m_Name && this->m_Age == p.m_Age) 49 { 50 return true; 51 } 52 return false; 53 } 54 55 string m_Name; 56 int m_Age; 57 }; 58 //利用find查找自定义数据类型 59 void test02() 60 { 61 vector<Person>v; 62 63 Person p1("aaa", 10); 64 Person p2("bbb", 20); 65 Person p3("ccc", 30); 66 Person p4("ddd", 40); 67 68 v.push_back(p1); 69 v.push_back(p2); 70 v.push_back(p3); 71 v.push_back(p4); 72 73 vector<int>::iterator pos = find(v.begin(), v.end(), p2); 74 if(pos != v.end()) 75 { 76 cout << "找到了数据,姓名:" << (*pos).m_Name << "年龄:" << pos->m_Age << endl; 77 } 78 else 79 { 80 cout << "未找到" << endl; 81 } 82 } 83 84 85 class MyCompare:public binary_function<Person*, Person*, bool> 86 { 87 public: 88 bool operator()(Person* p1, Person* p2) const 89 { 90 if(p1->m_Name = p2->m_Name && p1->m_Age == p2->m_Age) 91 { 92 return true; 93 } 94 return false; 95 } 96 97 }; 98 99 void test03() 100 { 101 vector<Person*>v; 102 103 Person p1("aaa", 10); 104 Person p2("bbb", 20); 105 Person p3("ccc", 30); 106 Person p4("ddd", 40); 107 108 v.push_back(&p1); 109 v.push_back(&p2); 110 v.push_back(&p3); 111 v.push_back(&p4); 112 113 Person* p = new Person("bbb", 20); 114 vector<Person*>::iterator pos = find_if(v.begin(), v.end(), bind2nd(MyCompare(), p)); 115 if(pos != v.end()) 116 { 117 cout << "找到了数据,姓名:" << (*pos)->m_Name << "年龄:" << (*pos)->m_Age << endl; 118 } 119 else 120 { 121 cout << "未找到" << endl; 122 } 123 124 125 } 126 127 /* 128 adjacent_find算法 查找相邻重复元素 129 @param beg 容器开始迭代器 130 @param end 容器结束迭代器 131 @param _callback 回调函数或者谓词(返回bool类型的函数对象) 132 @return 返回相邻元素的第一个位置的迭代器 133 */ 134 void test04() 135 { 136 vector<int>v; 137 v.push_back(2); 138 v.push_back(3); 139 v.push_back(4); 140 v.push_back(5); 141 v.push_back(5); 142 v.push_back(6); 143 v.push_back(2); 144 145 vector<int>::iterator pos = adjacent_find(v.begin(), v.end()); 146 if(pos != v.end()) 147 { 148 cout << "找到了相邻重复数据,为:" << *pos << endl; 149 } 150 else 151 { 152 cout << "未找到" << endl; 153 } 154 155 } 156 157 158 /* 159 binary_search算法 二分查找法 160 注意: 在无序序列中不可用 161 @param beg 容器开始迭代器 162 @param end 容器结束迭代器 163 @param value 查找的元素 164 @return bool 查找返回true 否则false 165 */ 166 void test05() 167 { 168 vector<int>v; 169 for(int i = 0; i < 10; i++) 170 { 171 v.push_back(i); 172 } 173 bool ret = binary_search(v.begin(), v.end(), 4); 174 if(ret) 175 { 176 cout << "找到了" << endl; 177 } 178 else 179 { 180 cout << "未找到" << endl; 181 } 182 183 } 184 185 /* 186 count算法 统计元素出现次数 187 @param beg 容器开始迭代器 188 @param end 容器结束迭代器 189 @param value回调函数或者谓词(返回bool类型的函数对象) 190 @return int返回元素个数 191 */ 192 193 /* 194 count算法 统计元素出现次数 195 @param beg 容器开始迭代器 196 @param end 容器结束迭代器 197 @param callback 回调函数或者谓词(返回bool类型的函数对象) 198 @return int返回元素个数 199 */ 200 class GreaterThanFour 201 { 202 public: 203 bool operator()(int v) 204 { 205 return v >= 4; 206 } 207 208 }; 209 210 void test06() 211 { 212 vector<int>v; 213 for(int i = 0; i < 10; i++) 214 { 215 v.push_back(i); 216 } 217 v.push_back(4); 218 v.push_back(4); 219 v.push_back(4); 220 v.push_back(4); 221 222 int num = count(v.begin(), v.end(), 4); 223 cout << "4的个数为:" << num << endl; 224 225 int num2 = count_if(v.begin(), v.end(), GreaterThanFour()); 226 cout << "4的个数为:" << num2 << endl; 227 } 228 229 230 231 int main() 232 { 233 test01(); 234 235 system("pause"); 236 return EXIT_SUCCESS; 237 }
7、常用排序算法
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<algorithm> 5 #include<vector> 6 #include<functional> 7 #include<ctime> 8 /* 9 merge算法 容器元素合并,并存储到另一容器中,注意:这两个容器必须有序 10 @param beg1 容器1开始迭代器 11 @param end1 容器1结束迭代器 12 @param beg2 容器2开始迭代器 13 @param end2 容器2结束迭代器 14 @param dest 目标容器开始迭代器 15 */ 16 17 18 void test01() 19 { 20 vector<int>v1; 21 vector<int>v2; 22 23 for(int i = 0; i < 10; i++) 24 { 25 v1.push_back(i); 26 v2.push_back(i + 1); 27 } 28 29 vector<int>vTarget; 30 vTarget.resize(v1.size() + v2.size()); 31 32 merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); 33 34 for_each(vTarget.begin(), vTarget.end(), [](int val){ cout << val << "";}); 35 } 36 37 /* 38 sort算法 容器元素排序 39 注意:两个容器必须是有序的 40 @param beg 容器1开始迭代器 41 @param end 容器1结束迭代器 42 @param _callback 回调函数或者谓词(返回bool类型的函数对象) 43 */ 44 void test02() 45 { 46 vector<int>v; 47 48 v.push_back(10); 49 v.push_back(40); 50 v.push_back(20); 51 v.push_back(90); 52 v.push_back(50); 53 54 sort(v.begin(), v.end());//默认升序 55 56 for_each(v.begin(), v.end(), [](int val){ cout << val << "";}); 57 58 //降序 59 sort(v.begin(), v.end(), greater<int>()); 60 61 for_each(v.begin(), v.end(), [](int val){ cout << val << "";}); 62 } 63 64 /* 65 random_shuffle(iterator beg, iterator end) 66 对指定范围内的元素随机调整次序 67 @param beg 容器开始迭代器 68 @param end 容器结束迭代器 69 */ 70 void test03() 71 { 72 srand((unsigned int)time(NULL));//初始化种子 73 74 vector<int>v; 75 76 for(int i = 0; i < 10; i++) 77 { 78 v.push_back(i); 79 } 80 81 random_shuffle(v.begin(), v.end()); 82 83 for_each(v.begin(), v.end(), [](int val){ cout << val << "";}); 84 } 85 86 /* 87 reverse算法 反转指定范围的元素 88 @param beg 容器开始迭代器 89 @param end 容器结束迭代器 90 */ 91 void test04() 92 { 93 vector<int>v; 94 95 for(int i = 0; i < 10; i++) 96 { 97 v.push_back(i); 98 } 99 100 reverse(v.begin(), v.end()); 101 102 for_each(v.begin(), v.end(), [](int val){ cout << val << "";}); 103 } 104 105 106 107 int main() 108 { 109 test01(); 110 111 system("pause"); 112 return EXIT_SUCCESS; 113 }
8、常用拷贝和替换算法
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<vector> 5 #include<algorithm> 6 #include<iterator> 7 8 /* 9 copy算法 将容器内指定范围的元素拷贝到另一容器中 10 @param beg 容器开始迭代器 11 @param end 容器结束迭代器 12 @param dest 目标起始迭代器 13 */ 14 15 void test01() 16 { 17 vector<int>v; 18 for(int i = 0; i < 10; i++) 19 { 20 v.push_back(i); 21 } 22 23 vector<int>vTarget; 24 vTarget.resize(v.size()); 25 26 copy(v.begin(), v.end(), vTarget.begin()); 27 28 //for_each(vTarget.begin(), vTarget.end(), [](int val){ cout << val << " ";}); 29 //使用copy打印 30 copy(vTarget.begin(), vTarget.end(), ostream_iterator<int>(cout, " ")); 31 } 32 33 /* 34 replace算法 将容器内指定范围的旧元素修改为新元素 35 @param beg 容器开始迭代器 36 @param end 容器结束迭代器 37 @param oldvalue 旧元素 38 @param oldvalue 新元素 39 */ 40 /* 41 replace_if算法 将容器内指定范围满足条件的元素替换为新元素 42 @param beg 容器开始迭代器 43 @param end 容器结束迭代器 44 @param callback函数回调或者谓词(返回Bool类型的函数对象) 45 @param oldvalue 新元素 46 */ 47 class MyCompare 48 { 49 public: 50 bool operator()(int v) 51 { 52 return v > 3; 53 } 54 }; 55 56 void test02() 57 { 58 vector<int>v; 59 for(int i = 0; i < 10; i++) 60 { 61 v.push_back(i); 62 } 63 64 //需求:把容器中的3替换成300 65 replace(v.begin(), v.end(), 3, 300); 66 67 copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); 68 69 cout << endl; 70 //需求:把容器中所有大于3替换成3000 71 72 replace_if(v.begin(), v.end(), MyCompare(), 3000); 73 74 copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); 75 } 76 77 /* 78 swap算法 互换两个容器的元素 79 @param c1容器1 80 @param c2容器2 81 */ 82 void test03() 83 { 84 vector<int>v1; 85 for(int i = 0; i < 10; i++) 86 { 87 v1.push_back(i); 88 } 89 90 vector<int>v2; 91 v2.push_back(10); 92 v2.push_back(30); 93 v2.push_back(20); 94 v2.push_back(40); 95 96 cout << "交换前数据:" << endl; 97 98 copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); 99 cout << endl; 100 copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " ")); 101 cout << endl; 102 103 swap(v1, v2); 104 105 cout << "交换后数据:" << endl; 106 107 copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); 108 cout << endl; 109 copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " ")); 110 cout << endl; 111 112 } 113 114 115 116 117 int main() 118 { 119 test01(); 120 121 system("pause"); 122 return EXIT_SUCCESS; 123 }
9、常用算数生成算法
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<vector> 5 #include<alogrithm>//不好使 6 #include<numeric>//好使 7 #include<iterator> 8 9 /* 10 accumulate算法 计算容器元素累计总和 11 @param beg 容器开始迭代器 12 @param end 容器结束迭代器 13 @param value累加值 14 */ 15 16 void test01() 17 { 18 vector<int>v; 19 for(int i = 0; i <= 100; i++) 20 { 21 v.push_back(i); 22 } 23 24 //0~100累积和 5050 25 //第三个参数,起始累加值 26 int sum = accumulate(v.begin(), v.end(), 0); 27 28 cout << "总和为:" << sum << endl; 29 30 } 31 32 /* 33 fill算法 向容器中添加元素 34 @param beg 容器开始迭代器 35 @param end 容器结束迭代器 36 @param value t填充元素 37 */ 38 void test02() 39 { 40 vector<int>v; 41 v.resize(10); 42 fill(v.begin(), v.end(), 1000);//相当于v.resize(10,1000); 43 44 copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); 45 46 } 47 48 49 int main() 50 { 51 test01(); 52 53 system("pause"); 54 return EXIT_SUCCESS; 55 }
10、常用集合算法
练习:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 #include<algorithm> 5 #include<vector> 6 #include<iterator> 7 8 /* 9 set_intersection算法 求两个set集合的交集 10 注意:两个集合必须是有序序列 11 @param beg1 容器1开始迭代器 12 @param end1 容器1结束迭代器 13 @param beg2 容器2开始迭代器 14 @param end2 容器2结束迭代器 15 @param dest 目标容器开始迭代器 16 @return 目标容器的最后一个元素的迭代器地址 17 */ 18 19 void test01() 20 { 21 vector<int>v1; 22 vector<int>v2; 23 24 for(int i = 0; i < 10; i++) 25 { 26 v1.push_back(i); 27 v2.push_back(i + 5); 28 } 29 30 vector<int>vTarget; 31 vTarget.resize(min(v1.size(), v2.size())); 32 33 vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); 34 35 copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));//使用itEnd可以保证不输出0 36 37 } 38 39 /* 40 set_union算法 求两个set集合的并集 41 注意:两个集合必须是有序序列 42 @param beg1 容器1开始迭代器 43 @param end1 容器1结束迭代器 44 @param beg2 容器2开始迭代器 45 @param end2 容器2结束迭代器 46 @param dest 目标容器开始迭代器 47 @return 目标容器的最后一个元素的迭代器地址 48 */ 49 void test02() 50 { 51 vector<int>v1; 52 vector<int>v2; 53 54 for(int i = 0; i < 10; i++) 55 { 56 v1.push_back(i); 57 v2.push_back(i + 5); 58 } 59 60 vector<int>vTarget; 61 vTarget.resize(v1.size() + v2.size()); 62 63 vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); 64 65 copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " ")); 66 67 } 68 69 /* 70 set_difference算法 求两个set集合的差集 71 注意:两个集合必须是有序序列 72 @param beg1 容器1开始迭代器 73 @param end1 容器1结束迭代器 74 @param beg2 容器2开始迭代器 75 @param end2 容器2结束迭代器 76 @param dest 目标容器开始迭代器 77 @return 目标容器的最后一个元素的迭代器地址 78 */ 79 void test03() 80 { 81 vector<int>v1; 82 vector<int>v2; 83 84 for(int i = 0; i < 10; i++) 85 { 86 v1.push_back(i); 87 v2.push_back(i + 5); 88 } 89 90 vector<int>vTarget; 91 vTarget.resize(max(v1.size(), v2.size())); 92 93 //v1差v2 94 vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); 95 96 copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " ")); 97 98 cout << endl; 99 100 //v2差v1 101 vector<int>::iterator itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget.begin()); 102 103 copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " ")); 104 } 105 106 107 int main() 108 { 109 test01(); 110 111 system("pause"); 112 return EXIT_SUCCESS; 113 }
11、综合案例——学校演讲比赛
》比赛规则:某市举行一场演讲比赛( speech_contest ),共有24个人参加。比赛共三轮,前两轮为淘汰赛,第三轮为决赛。
》比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;
>第一轮分为4个小组,每组6个人。比如编号为: 100-123. 整体进行抽签(draw)后顺序演讲。当小组演讲完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
>第二轮分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
>第三轮只剩下1组6个人,本轮为决赛,选出前三名。
》比赛评分:10个评委打分,去除最低、最高分,求平均分每个选手演讲完由10个评委分别打分。该选手的最终得分是去掉一个最高分和一个最低分,求得剩下的8个成绩的平均分。选手的名次按得分降序排列。
用STL编程,求解这个问题
1)请打印出所有选手的名字与参赛号,并以参赛号的升序排列。
2)打印每一轮比赛后,小组比赛成绩和小组晋级名单
三、总结
1 函数对象(仿函数)
1.1 重载 () 所以函数的对象 使用()像函数调用
1.2 是类 而不是普通的函数
1.3 内部记录状态
1.4 作为类型 与模板进行配合使用
2 谓词
2.1 普通函数或者仿函数返回值 bool类型
2.2 一元 一个参数 二元 两个参数
2.3 一元 查找 大于20的数字 find_if 返回迭代器
2.4 二元 排序
3 内建函数对象
3.1 取反
3.2 加法
3.3 大于 greater<int>()
4 适配器
4.1 函数适配器
4.2 0~9 加起始值 进行输出 用户提供起始值
4.3 bind2nd 绑定
4.4 继承 binary_function<参数类型1,参数类型2,返回值类型>
4.5 const修饰 operator()
4.6 取反适配器
4.6.1 not1 一元 找出小于5
4.6.2 not2 二元 排序 not2( less<int>() ) 从大到小 相当于 greater<int>()
4.7 普通函数指针适配
4.7.1 ptr_fun
4.8 成员函数适配
4.8.1 //如果容器存放的是对象指针, 那么用mem_fun
4.8.2 //如果容器中存放的是对象实体,那么用mem_fun_ref
5 常用遍历算法
5.1 for_each 可有有返回值
5.2 可以绑定参数进行输出
5.3 transform 将容器中的数据进行搬运到另一个容器中
5.4 注意:目标容器需要开辟空间
6 常用查找算法
6.1 find 按值查找 Person
6.2 find_if 按条件查找 Person*
6.3 adjacent_find算法 查找相邻重复元素 返回第一个重复元素的迭代器位置
6.4 binary_search算法 二分查找法 必须容器是有序序列
6.5 count 和count_if
7 常用排序算法
7.1 merge算法 容器元素合并,并存储到另一容器中,两容器要有序,并且顺序一致
7.2 sort 排序
7.3 random_shuffle 洗牌 自己提供随机种子
7.4 reverse反转
8 常用的拷贝和替换算法
8.1 copy复制
8.2 replace replace_if 替换
8.3 swap 交换
9 常用算数生成算法
9.1 头文件 numeric
9.2 accumulate 累加
9.3 fill 填充
10 常用集合算法
10.1 交集 set_intersection
10.2 并集 set_union
10.3 差集 set_difference
在学习c++提高-STL总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
posted on 2020-06-18 08:27 Alliswell_WP 阅读(143) 评论(0) 编辑 收藏 举报