• STL 容器(vector 和 list )


    1.这个容器的知识点比较杂

    迭代器的理解:
    1.erase()函数的返回值,它的迭代器在循环遍历中的奇特之处;

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include <iostream>
      3 #include <vector>
      4 #include <list>
      5 #include <algorithm>
      6 #include <numeric>
      7 #include <functional>
      8 
      9 using namespace std;
     10 
     11 /*
     12 int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 99};
     13 要求:
     14 (1)将ia复制到一个vector容器vec中和一个list容器中lst中。
     15 (2)将vec容器中的奇数值元素删除。
     16 (3)使用内置算法计算vec窗器所有元素的和。Accumulate
     17 (4)使用内置算法计算lst容器中大于5的元素的个数    count_if
     18 
     19 */
     20 
     21 //lambda 表达式
     22 // [](参数列表)->返回值 {函数体}
     23 
     24 
     25 void print(int val)                //回调函数
     26 {
     27     cout << val << " ";
     28 }
     29 //打印的三种方式(回调函数、函数对象、兰巴达表达式)
     30 struct PRINT
     31 {
     32     void operator()(int val)
     33     {
     34         cout << val << " ";
     35     }
     36 };
     37 void printVec(vector<int>& v)
     38 {
     39     for_each(v.begin(), v.end(), [](int val){cout << val << " "; });        //采用兰博打表达式
     40     cout << endl;
     41 }
     42 
     43 void printList(list<int>&  L)            //这里采用了回调函数,函数对象
     44 {
     45     //for_each(L.begin(), L.end(), PRINT());            //回调函数对象
     46     for_each(L.begin(), L.end(), print);            //回调函数
     47     cout << endl;
     48 }
     49 
     50 class isGreat
     51 {
     52 public:
     53     bool operator()(int val)
     54     {
     55         if (val > 5)
     56             return true;
     57         else
     58             return false;
     59     }
     60 };
     61 void test04(int* arr, int len)
     62 {
     63     vector<int> v1;
     64     list<int> l1;
     65     v1.assign(arr, arr + len - 1);        //将数组中的元素拷贝进容器中(第一种方法)
     66     //将一个容器中的元素拷贝进另一个容器(第二种方法)
     67     for (int val : v1)                    //C++11的表达式;此处的v1可以是数组或容器
     68     {
     69         l1.push_back(val);
     70     }
     71     //打印
     72     printVec(v1);
     73     printList(l1);
     74 
     75     //(2)将vec容器中的奇数值元素删除。 erase
     76     vector<int>::iterator it = v1.begin();
     77     for (; it != v1.end(); )
     78     {
     79         if (*it % 2 != 0)
     80         {
     81             it = v1.erase(it);        //这里关注 erase 的返回值,是一个迭代器。
     82             //it--;            //这种方法不对,有bug;它是将迭代器的移动还放在for循环的位置(正常放置),但是当第一个元素符合条件时,这种方法就出错,因为迭代器减小后,就越界了。
     83         }
     84         else                        //同时还有这步,将迭代器的移动放到下面。(这种属于通用方法,但是我还没有想懂,它删除后迭代器是如何移动的)(现在搞懂了,在线面有详细描述)
     85         {
     86             it++;
     87         }
     88     }
     89     printVec(v1);
     90 
     91     //(3)使用内置算法计算vec窗器所有元素的和。Accumulate
     92     auto it1 = v1.begin();            //auto可以自动推导变量的类型。
     93     auto sum = accumulate(it1, v1.end(), 0);        //第三个参数为:求和的基数;即容器中所有的元素的和加上它就是最后的总和。
     94 
     95     //(4)使用内置算法计算lst容器中大于5的元素的个数
     96     int num = count_if(l1.begin(), l1.end(), isGreat());
     97     cout << num << endl;
     98 }
     99 
    100 int main()
    101 {
    102     int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 99 };
    103     int len = sizeof(ia) / sizeof(int);
    104     test04(ia, len);
    105 
    106     system("pause");
    107     return EXIT_SUCCESS;
    108 }

    1.这个题 的知识点:

      1)vector容器在遍历的时候删除元素;这个和 erase()函数的返回值有关

      2) erase()函数的返回值;(这个最重要)

      3)一个容器中元素拷贝到不同类型的容器中(三种方法,一种没写,为普通的for循环遍历)

      4)打印容器元素的三种方法:(回调函数,函数对象,兰巴达表达式)

      5)STL的求和函数 accumulate(),第三个参数的作用;

      6)auto类型;可以自动推导变量的类型

      7)查找count_if()函数的使用,第三个参数的作用。

    2.循环遍历,it++放置不同的位置;
      1)在正常的for循环位置
        1)符合条件时erase()容器中的某个元素,但是没有接返回值
        2)符合条件时erase()容器中的某个元素,接了返回值;
        3)符合条件时,接了返回值,同时在下面接着 it--;看容器首位元素符合条件和不符合条件的两种情况。
      2)不放在正常位置
        1)放在不符合条件的情况下it++;(即正确的情况,上面的那段代码)。

     1 void test01(vector<int> v)
     2 {                //这段代码会报错,因为当进行 erase() 后, 当前迭代器就失效了。而这里对它进行了++操作,所以程序崩溃
     3     for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
     4     {
     5         if (*it % 2 != 0)                
     6         {
     7             v.erase(it);
     8         }
     9     }
    10 }
    11 
    12 void test02(vector<int> v)
    13 {
    14     for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    15     {            //这段代码也会崩溃,erase()函数的返回值被接收,此时假如最后一个数据也符合条件,代码运行到最后的数据,也会崩溃。
    16         if (*it % 2 != 0)
    17         {
    18             it = v.erase(it);
    19         }
    20     }
    21 }
    22 
    23 for (vector<int>::iterator it = v.begin(); it != v1.end(); it++)
    24 {
    25     cout << *it << " ";
    26     if (*it % 2 != 0)
    27     {
    28         v1.erase(it);        //这里关注 erase 的返回值,是一个迭代器。如果接受这个迭代器,那么此时它就指向删除元素的下一个元素。
    29         it--;            //这种方法不对,有bug;它是将迭代器的移动还放在for循环的位置(正常放置),但是当第一个元素符合条件时,这种方法就出错,因为迭代器减小后,就越界了。
    30     }                    //但是假如第一个数据不符合条件就没有问题。
    31 }
    1 /*
    2 vector<int> 容器 erase() 的返回值为"当前位置的"迭代器;它是这样理解的;假如你不接返回值,那么遍历循环时,删除后的当前迭代器
    3 值失效,而你接下来还对它进行了操作,编译器马上段错误。
    4  当你对它的返回值接收后,(就像紧密排列在一起的球,拿掉其中的一个,下一个立刻补上,);虽然返回的是同一个位置的迭代器,但是它
    5  值已经发生变化,(相对于原来的容器来说,他就返回了属于后一个值得迭代器。)而这个迭代器是有效的,你可以对它进行操作。(但是此时
    6  还有一些额外情况,例如:当容器最后一个数据符合条件,它的迭代器被删除,而又被接到返回值,此时这个迭代器就是尾部的 end()迭代器,
    7  假如遍历的循环,第三个条件还写在与原来的位置,如(++操作),此时就会发生迭代器的越界,编译器出现段错误。(在下面有实例)。
    8 
    9 */

    3.sort算法排序【包含:函数对象(仿函数)】;

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<vector>
     4 #include<algorithm>
     5 #include<functional>
     6 #include<string>
     7 using namespace std;
     8 
     9 //sort排序算法
    10 struct for_each_condition{
    11     void operator()(int val){
    12         cout << val << " ";
    13     }
    14 };
    15 void test01(){
    16 
    17     vector<int> v;
    18     v.push_back(10);
    19     v.push_back(20);
    20     v.push_back(80);
    21     v.push_back(90);
    22     v.push_back(50);
    23     v.push_back(40);
    24 
    25     for_each(v.begin(), v.end(), for_each_condition()); cout << endl;
    26     sort(v.begin(), v.end(), less<int>());
    27     for_each(v.begin(), v.end(), for_each_condition()); cout << endl;
    28     sort(v.begin(), v.end(), greater<int>());
    29     for_each(v.begin(), v.end(), for_each_condition()); cout << endl;
    30 }
    31 
    32 class Person{
    33 public:
    34     Person(string name, int age){
    35         this->mName = name;
    36         this->mAge = age;
    37     }
    38     bool operator==(const Person& p){
    39         if (p.mName == this->mName && this->mAge == p.mAge){
    40             return true;
    41         }
    42         return false;
    43     }
    44 public:
    45     string mName;
    46     int mAge;
    47 };
    48 
    49 //排序对象
    50 struct for_each_condition_obj{
    51     void operator()(Person& val){
    52         cout << "Name:" << val.mName << " Age:" << val.mAge << endl;
    53     }
    54 };
    55 struct sort_condition{
    56     bool operator()(Person& p1, Person& p2){
    57         return p1.mAge > p2.mAge;
    58     }
    59 };
    60 void test02(){
    61 
    62     vector<Person> v;
    63     v.push_back(Person("john01", 30));
    64     v.push_back(Person("john03", 32));
    65     v.push_back(Person("john05", 34));
    66     v.push_back(Person("john02", 31));
    67     v.push_back(Person("john06", 35));
    68     v.push_back(Person("john03", 32));
    69 
    70     for_each(v.begin(), v.end(), for_each_condition_obj()); cout << endl;
    71     sort(v.begin(), v.end(), sort_condition());
    72     for_each(v.begin(), v.end(), for_each_condition_obj()); cout << endl;
    73 }
    74 int main(){
    75 
    76     //test01();
    77     test02();
    78 
    79     system("pause");
    80     return EXIT_SUCCESS;
    81 }
    
    
  • 相关阅读:
    delphi的dbgrid控件点击title排序
    在 Delphi 中使用微软全文翻译的小例子
    Google的搜索API的Delphi封装
    Delphi 自动检测U盘插入、拔出及获取U盘盘符!
    ERP开发准备
    Delphi中TStringList类常用属性方法详解
    JavaScript prototype详解
    TestNG 自动化测试入门教程--典型示例
    ucloud中的udisk错误“Read-only file system”修复指南
    websocket(二)--简单实现网页版群聊
  • 原文地址:https://www.cnblogs.com/yyx1-1/p/5778205.html
Copyright © 2020-2023  润新知