天天看點

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、綜合案例——學校演講比賽

c++提高學習筆記——05-c++STLday12

》比賽規則:某市舉行一場演講比賽( speech_contest ),共有24個人參加。比賽共三輪,前兩輪為淘汰賽,第三輪為決賽。

》比賽方式:分組比賽,每組6個人;選手每次要随機分組,進行比賽;

>第一輪分為4個小組,每組6個人。比如編号為: 100-123.  整體進行抽簽(draw)後順序演講。當小組演講完後,淘汰組内排名最後的三個選手,然後繼續下一個小組的比賽。

>第二輪分為2個小組,每組6人。比賽完畢,淘汰組内排名最後的三個選手,然後繼續下一個小組的比賽。

>第三輪隻剩下1組6個人,本輪為決賽,選出前三名。

》比賽評分:10個評委打分,去除最低、最高分,求平均分每個選手演講完由10個評委分别打分。該選手的最終得分是去掉一個最高分和一個最低分,求得剩下的8個成績的平均分。選手的名次按得分降序排列。

c++提高學習筆記——05-c++STLday12

用STL程式設計,求解這個問題

1)請列印出所有選手的名字與參賽号,并以參賽号的升序排列。

2)列印每一輪比賽後,小組比賽成績和小組晉級名單