zoukankan      html  css  js  c++  java
  • 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~

      

  • 相关阅读:
    VBE2019、VBE2014、VBE2014_VB6三合一的下载、安装和使用(最新版2020.09.09)
    调用其他VBA工程中的过程和函数以及API函数
    QQ消息群发助手SendQQMessage的下载和使用
    VBA/VB6/VBS/VB.NET/C#/Python/PowerShell都能调用的API封装库
    Excel-DNA项目只用1个文件实现Ribbon CustomUI和CustomTaskpane定制【C#版】
    Excel-DNA项目只用1个文件实现Ribbon CustomUI和CustomTaskpane定制【VB.Net版】
    VSTO外接程序项目只用1个文件实现Ribbon CustomUI和CustomTaskpane定制【C#版】
    VSTO外接程序项目只用1个文件实现Ribbon CustomUI和CustomTaskpane定制【VB.Net版】
    Outlook邮件的右键菜单中添加自定义按钮
    VBA自动点击IE的浏览按钮、自动选择路径、自动关闭打开文件对话框
  • 原文地址:https://www.cnblogs.com/Jiangxingchen/p/13304302.html
Copyright © 2011-2022 走看看