在学习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个成绩的平均分。选手的名次按得分降序排列。
三、总结
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,转载请注明出处。