C++知识点 STL容器1—vector

~vector~

  vector可能是与各位选手见面次数最多的STL容器了

  这是因为它在图论问题中发挥的特殊而重要的作用

  简单来说vector就是一个能根据需求改变自己长度的数组

  它有一个空间的初始值,一旦初始值满则向内存申请两倍的空间

  同样的,它支持像数组一样使用下标访问,(不是修改

  也像数组一样不能O(1)在任意位置插入元素(链表才有这种性质)

  要实现非首尾插入必须将插入位置的后面元素整体后移1才能实现

  所以为保证效率,元素的插入与删除应该在数组尾进行

  看下代码实现

  //如何建一个vector
  #include <vector>//每种容器都有单独的头文件
  using namespace std;
  int main() {
     vector <int> a;//直接声明了一个叫做a的可变长一维数组
      vector <int> b[233];
      //声明了一个第一维长度固定为233,第二位长度可变的二维数组
      struct Node{
          long long val, tag1, tag2;
          Node *rs, *ls;
      }vector <Node> c;
      //将名为Node的结构体压入一个vector
      //结构体同样也可以存放在vector中,这点和数组一样
      return 0;
  }

  建好了vector便可以对它进行操作了

  首先是输入

  和数组一样一样的操作

  伪代码就是

  vector <int> a;
  for(int i = 1; i <= n; i++)
  cin>>a[i];

  这里没什么可说的

  这里很有必要说一下

  vector和数组最大的区别就是不能修改中间元素

  必须从队尾使用bush_back函数加入新元素

  用pop_back函数删除vector最后一个元素

  像上面被删除的伪代码一样操作会直接导致程序崩溃

  来看这波代码实现

 #include <iostream>
 #include <vector>
 using namespace std;
 vector<int>s;
 int main()
 {
int n; cin>>n; for(int i = 0; i < n; i++) { //输入4 1 2 3 1 int x; cin>>x;
s.push_back(x); }
for(int j = 0; j < n; j++) cout<<s[j]<<" "; return 0; }     

 

  这里要特别注意的是

  使用push_back从队尾插入元素时

  第一个元素会默认插入a[0]中,而不是a[1]

  我们讲完了vector的声明储存和插入

  再来看size,empty,和clear函数  

  size返回的是一个整形,表示该vector中真实存在的元素

  empty返回一个布尔,判断该vector是否为空,bool为true则vector为空

  clear则可以清空一个vector

  看下代码实现  

#include <iostream>
#include <vector>
using namespace std;
vector<int>s;
int main()
{
    int n;
    cin>>n;
    for(int i = 0; i < n; i++)
    {
        //输入4 1 2 3 1
        int x;
        cin>>x;
        s.push_back(x);
    }
    cout<<"vector s 的大小是"<<s.size()<<endl;
    if(!s.empty())
    cout<<"s 不为空"<<endl;
    else
    cout<<"s 为空"<<endl;
    s.clear();
    if(!s.empty())
    cout<<"s 不为空"<<endl;
    else
    cout<<"s 为空"<<endl;
    return 0;
}

      输出结果为:

4
s 不为空
s 为空

  看完这些对vector空间的操作    

  我们再来看vector中的迭代器

  这些玩意类似于指针

  同样可以用*和->操作

  首先我们可以通过

  vector<int>::iterator it;

  声明一个叫做it的int类型的vector迭代器

  那我们这时候又不得不学两个函数

  一个叫begin,一个叫end

  begin返回的是vector的队首迭代器

  end返回的则是vector的队尾的后一个元素的迭代器

  基本上和指针大差不差

  我们看一下代码实现

 #include <iostream>
 #include <vector>
 using namespace std;
 vector<int>s;
 int main()
 {
     int n;
     cin>>n;
     for(int i = 0; i < n; i++)
     {
         //4 1 2 3 1
         int x;
         cin>>x;
         s.push_back(x);
      }
       cout<<*s.begin()<<endl;//*和对指针的意义相同
        cout<<*s.end()<<endl;for(vector<int>::iterator it = s.begin(); it != s.end(); it++)
      cout<<*it<<" ";
      return 0; 
}

      如果你认为充分理解了这段代码所传达的含义

  建议把它粘贴到编译器中运行一下

  啊这

  第三行我们本来期望输出此时的队尾元素1的

  却出现了个诡异的数字

  这就说明你还是没理解(大雾

  end函数返回的是队尾的后一个元素

  此时这个元素是不存在也就是没有被插入的

  于是乎就出现了个诡异的数

  要想访问队尾元素

  我们既可以直接s[n-1]

  也可以访问*s.end()--,也就是访问s.end()的前面内个元素(队尾元素

  还有个叫back的函数

  s.back()等价于*s.end()--

  (与back相对的front函数则与*s.begin()或者s[0]等价

  由于我们刚才for语句中it != s.end(),

  所以当it成为队尾元素迭代器时就停止了,不会触碰下一个没有被插入的节点

  vector至此即可告一段落

  最后来一波vector的代码总成

  希望读者在自己的机器上编译运行一下

  看看是什么效果,这些函数的作用都理解了

  vector也没有什么难懂的了(算法竞赛领域内

#include <iostream>
#include <vector>
using namespace std;
vector<int>s;
int main()
{
    int n;
    cin>>n;
    for(int i = 0; i < n; i++)
    {
        //输入5 1 2 3 4 5 
          int x;
        cin>>x;
        s.push_back(x);
    }
    cout<<s.front()<<endl;
    cout<<s.back()<<endl; 
    s.pop_back(); 
    cout<<*s.begin()<<endl;
    cout<<*s.end()<<endl;
    cout<<*--s.end()<<endl; 
    for(vector<int>::iterator it = s.begin(); it != s.end(); it++)
    cout<<*it<<" ";
    cout<<endl;
    cout<<s.size()<<endl;
    if(!s.empty())
    cout<<"s非空"<<endl;
    else
    cout<<"s已空"<<endl;
    s.clear();
    if(!s.empty())
    cout<<"s非空"<<endl;
    else
    cout<<"s已空"<<endl;
    return 0; 
}

~END~

  

posted @ 2020-07-15 16:16  JiangXingchen  阅读(227)  评论(0编辑  收藏  举报
Live2D