在學習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)列印每一輪比賽後,小組比賽成績和小組晉級名單