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 }

 

 

 


posted on 2016-08-16 22:56  路之遥_其漫漫  阅读(311)  评论(0编辑  收藏  举报

导航