C++STL标准库学习笔记(十)vector deque list


前言:

  在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来。

  在这一篇文章中,我们主要对vector deque list进行简单的介绍,(真的很简单的介绍,如果想要知道所有函数的用法的话,建议去看一下其他人的总结,我这里主要是记录一个学习过程,提供一个学习思路)

  因为它们的操作大多相同,就不一个个列举它们的操作了,一个优秀的IDE能自动提示“.”后面应该接什么,函数里面应该填什么,反复强调已经了解过的知识就有点冗杂了。

正文:

1. vector示例程序

 1 #include
 2 #include
 3 using namespace std;
 4 template<class T>
 5 void PrintVector(T s, T e)
 6 {
 7     for (; s != e; s++)
 8     {
 9         cout<<* s<<" ";
10     }
11     cout<<endl;
12 }
13 
14 int main(int argc, char const *argv[])
15 {
16     int a[5] = {1,2,3,4,5};
17     vector<int> v(a,a+5);
18     //用数组来构造vector
19     cout<<"1)"<//结果:1)5
20     cout<<"2)";
21     PrintVector(v.begin(),v.end());//结果:2)1 2 3 4 5
22     v.insert(v.begin() + 2, 13);
23     //在第二个元素后面插入元素
24     cout<<"3)";
25     PrintVector(v.begin(),v.end());//结果:3)1 2 13 3 4 5
26     v.erase(v.begin() + 2);
27     //删除迭代器指向的元素
28     cout<<"4)";
29     PrintVector(v.begin(),v.end());//结果:4)1 2 3 4 5
30     vector<int> v2(4,100);
31     //构造函数,创造四个元素值为100的vector
32     v2.insert(v2.begin(),v.begin() + 1,v.begin() + 3);//将v的一段插入v2的开头
33     cout<<"5) v2:";
34     PrintVector(v2.begin(),v2.end());//结果:5) v2:2 3 100 100 100 100
35     v2.erase(v.begin()+1, v.begin()+3);
36     //删除了v的一个区间,即2,3
37     cout<<"6)";
38     PrintVector(v.begin(),v.end());//结果:6)1 4 5
39     return 0;
40 }

  老样子,找出其中重要的部分来细锁。

    int a[5] = {1,2,3,4,5};

    vector v(a,a+5);

  这里是建立了一个int数组,然后用这个数组来创造一个vector。

    v.end() - v.begin()

  这个在这个程序中的结果是5,说明vector的迭代器是随机访问迭代器,毕竟只有它才能实现加减操作。

    v.insert(v.begin() + 2, 13);

  在第二个元素后面插入13(不就是在下标2插入元素然后后面的元素集体后移吗),没什么需要特别强调的。

    v.erase(v.begin() + 2);

  删除第二个元素后面(不就是下标为2的元素吗)的元素。

    vector v2(4,100);

  构造函数,v2包含四个值为100的元素。(充分体现了STL标准库的聪明机智,直接省去麻烦的一个个赋值)

    v2.insert(v2.begin(),v.begin() + 1,v.begin() + 3);

  在v2的开头插入v的下标为1到下标为2(1和3的左闭右开区间)的元素。(STL标准库普遍如此)

    v2.erase(v.begin()+1, v.begin()+3);

  擦去下标为1和2的元素([1,3)的元素)

 

2. 用vector实现二维数组

  样例:

 1 #include
 2 #include
 3 using namespace std;
 4 
 5 int main(int argc, char const *argv[])
 6 {
 7     vectorint>>v(3);
 8     //v有3个元素,每个元素都是vector容器
 9     for (int i = 0; i < v.size(); i++)
10     {
11         for (int j = 0; j < 4; j++)
12         {
13             v[i].push_back(j);
14         }
15     }
16     for (int i = 0; i < v.size(); i++)  
17     {
18         for (int j = 0; j < 4; j++)
19         {
20             cout<" ";
21         }
22         cout<<endl;
23     }
24     /*
25     结果:
26     0 1 2 3
27     0 1 2 3
28     0 1 2 3
29     */
30     return 0;
31 }

  从本质上来看,就是套娃,但是它的元素可以通过v[i][j]来调用,可以说是非常方便的

  注意:

    vector >v(3);

  在定义时,里面的vector后面要记得跟一个空格,部分编译器可能会把两个“>”号看成右移运算符

 

3. deque

  双向队列

  所有适用于vector的操作都适用于deque

  deque还有push_front(将元素插入到前面)和pop_front(删除最前面的元素)操作,复杂度是O(1)

 

4. list容器

  双向链表

  它的底层实现不是数组,所以不支持随机存取

  在任何位置插入删除都是常数时间,不支持随机存取

  除了具有所有顺序容器都具有的成员函数以外(差不多vector有的它都有),还支持8个成员函数:

    push_front:在前面插入

    pop_front:删除前面的元素

    sort:排序(list不支持STL的算法sort)(毕竟这是list,而不是数组之类,STL库的sort算法只支持可以随机访问的迭代器)

    remove:删除和指定值相等的所有元素

    unique:删除所有和前一个元素相同的元素(要做到元素不重复,则unique之前还需要sort)

    merge:合并两个链表,并清空被合并的那个

    reverse:颠倒链表

    splice:在指定位置前面插入另一链表中的一个或多个元素,并在另一链表中删除被插入的元素

  样例:

  1 #include
  2 #include
  3 #include
  4 using namespace std;
  5 
  6 class A
  7 {
  8 private:
  9     int n;
 10 public:
 11     A(int n_) { n = n_;}
 12     friend bool operator<( const A & a1, const A & a2);
 13     friend bool operator==( const A & a1, const A & a2);
 14     friend ostream & operator<<( ostream & o, const A & a);
 15 };
 16 bool operator<(const A & a1, const A & a2)
 17 {
 18     return a1.n < a2.n;
 19 }
 20 bool operator==(const A & a1, const A & a2)
 21 {
 22     return a1.n == a2.n;
 23 }
 24 ostream & operator<<( ostream & o, const A & a)
 25 {
 26     o << a.n;
 27     return o;
 28 }
 29 template<class T>
 30 void PrintList(const list & lst)
 31 {//不推荐的写法,还是用两个迭代器作为参数会更好
 32     typename list::const_iterator i;
 33     i = lst.begin();
 34     for ( i = lst.begin(); i != lst.end(); i++)
 35     {
 36         cout<< *i << ",";
 37     }
 38     //typename可以用来说明list::const_iterator是个类型
 39     //在vs中不写也可以
 40 }
 41 
 42 
 43 
 44 int main(int argc, char const *argv[])
 45 {
 46     list lst1,lst2;
 47     lst1.push_back(1);
 48     lst1.push_back(2);
 49     lst1.push_back(3);
 50     lst1.push_back(4);
 51     lst1.push_back(2);
 52 
 53     lst2.push_back(10);
 54     lst2.push_front(20);
 55     lst2.push_back(30);
 56     lst2.push_back(30);
 57     lst2.push_back(30);
 58     lst2.push_front(40);
 59     lst2.push_back(40);
 60 
 61     cout<<"1)";
 62     PrintList(lst1);
 63     cout<//输出:1)1,2,3,4,2,
 64     cout<<"2)";
 65     PrintList(lst2);
 66     cout<//输出:2)40,20,10,30,30,30,40,
 67 
 68     lst2.sort();
 69     cout<<"3)";
 70     PrintList(lst2);
 71     cout<//输出:3)10,20,30,30,30,40,40,
 72 
 73     lst2.pop_front();
 74     cout<<"4)";
 75     PrintList(lst2);
 76     cout<//输出:4)20,30,30,30,40,40,
 77 
 78     lst1.remove(2);//删除所有和A(2)相等的元素
 79     cout<<"5)";
 80     PrintList(lst1);
 81     cout<//输出:5)1,3,4,
 82 
 83     lst2.unique();//删除所有和前一个元素相等的元素
 84     cout<<"6)";
 85     PrintList(lst2);
 86     cout<//输出:6)20,30,40,
 87 
 88     lst1.merge(lst2);//合并lst2到lst1并清空lst2
 89     cout<<"7)";
 90     PrintList(lst1);
 91     cout<//输出:7)1,3,4,20,30,40,
 92 
 93     cout<<"8)";
 94     PrintList(lst2);
 95     cout<//输出:8)
 96 
 97     lst1.reverse();
 98     cout<<"9)";
 99     PrintList(lst1);
100     cout<//输出:9)40,30,20,4,3,1,
101 
102     lst2.push_back(100);
103     lst2.push_back(200);
104     lst2.push_back(300);
105     lst2.push_back(400);
106     list::iterator p1,p2,p3;
107     p1 = find(lst1.begin(),lst1.end(),3);
108     p2 = find(lst2.begin(),lst2.end(),200);
109     p3 = find(lst2.begin(),lst2.end(),400);
110     lst1.splice(p1,lst2,p2,p3);
111     //将[p2,p3)插入p1之前,并从lst2中删除[p2,p3)
112 
113     cout<<"10)";
114     PrintList(lst1);
115     cout<//输出:10)40,30,20,4,200,300,3,1,
116     cout<<"11)";
117     PrintList(lst2);
118     cout<//输出:11)100,400,
119 
120     return 0;
121 }
样例3

  这个样例基本把list的主要用法都包含进去了。

 

后记:

  这些东东基本上都是那种你知道了一个,其他的就都能推导出来的那种知识,如果不想死记硬背的话,其实用好IDE自带的功能,记好基本的用法就能自由使用了。放假了,不能摸鱼,要认真学习,为将来做好准备(生怕被淘汰的我)。