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,转载请注明出处。

原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_ImprovedLearning_03.html