zoukankan      html  css  js  c++  java
  • 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,转载请注明出处。

  • 相关阅读:
    PE文件简介
    hook键盘驱动中的分发函数实现键盘输入数据的拦截
    遍历系统中加载的驱动程序以及通过设备对象指针获取设备对象名称
    如何利用git shell提交代码到github
    驱动开发中的常用操作
    3.1_栈_顺序存储结构(数组形式)
    2.6_链表深入
    2.5_线性表的链式存储结构_双向链表
    2.4_线性表的链式存储结构_单链表具体实现
    2.3_线性表的链式存储结构_单链表
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_ImprovedLearning_03.html
Copyright © 2011-2022 走看看