zoukankan      html  css  js  c++  java
  • 跟我一起学STL(2)——vector容器详解

    一、引言

    在上一个专题中,我们介绍了STL中的六大组件,其中容器组件是大多数人经常使用的,因为STL容器是把运用最广的数据结构实现出来,所以我们写应用程序时运用的比较多。然而容器又可以序列式容器和关联式容器两类,C++语言本身提供了一个序列式容器数组,另外STL又提供vector,list,deque等序列式容器,本专题将详细介绍下vector容器。

    二、vector详解

    2.1 vector容器介绍

    vector容器的数据结构为单端数组,其操作方式与数组的操作非常相似,唯一不同的是——数组是静态空间,一旦配置了数组大小就不能改变,而vector是动态空间,随着元素的插入,vector类内部机制会自行扩充空间来容纳新的元素,我们不需要担心因为空间不足而一开始就申请一个空间较大的数组,使用vector更加灵活。vector与C++中数组的区别,如.NET中List<T>类与数组的区别一样。

    2.2 vector对象创建详解

    vector有8个构造函数,其8个构造函数的定义如下代码所示:

           // 默认无参构造函数
     vector()
            : _Mybase()
            {    // construct empty vector
            }
            // 
        explicit vector(const _Alloc& _Al)
            : _Mybase(_Al)
            {    // construct empty vector with allocator
            }
    
        explicit vector(size_type _Count)
            : _Mybase()
            {    // construct from _Count * _Ty()
            resize(_Count);
            }
    
       vector(size_type _Count, const _Ty& _Val)
            : _Mybase()
            {    // construct from _Count * _Val
            _Construct_n(_Count, _STD addressof(_Val));
            }
    
        vector(size_type _Count, const _Ty& _Val, const _Alloc& _Al)
            : _Mybase(_Al)
            {    // construct from _Count * _Val, with allocator
            _Construct_n(_Count, _STD addressof(_Val));
            }
            // 拷贝构造函数
        vector(const _Myt& _Right)
            : _Mybase(_Right._Alval)
            {    // construct by copying _Right
            if (_Buy(_Right.size()))
                _TRY_BEGIN
                this->_Mylast = _Ucopy(_Right.begin(), _Right.end(),
                    this->_Myfirst);
                _CATCH_ALL
                _Tidy();
                _RERAISE;
                _CATCH_END
            }
           
        template<class _Iter>
            vector(_Iter _First, _Iter _Last)
            : _Mybase()
            {    // construct from [_First, _Last)
            _Construct(_First, _Last, _Iter_cat(_First));
            }
    
        template<class _Iter>
            vector(_Iter _First, _Iter _Last, const _Alloc& _Al)
            : _Mybase(_Al)
            {    // construct from [_First, _Last), with allocator
            _Construct(_First, _Last, _Iter_cat(_First));
            } 

    下面演示下利用上面的构造函数来创建不同的vector对象,并输出每个vector对象中的元素,具体演示代码如下所示:

    // 额外引入vector头文件
    #include <vector>
    #include <iostream>
    using namespace std;
    void main()
    {
        // 使用_Vector_iterator<int>类默认无参构造函数初始化6个迭代器对象
        vector<int>::iterator v1_Iter,v2_Iter,v3_Iter,v4_Iter,v5_Iter,v6_Iter;
        // 创建一个空的vector对象v0,调用了①构造函数
        vector<int> v0;
    
        // 创建vector对象v1,v1包含3个默认值为0的元素,调用③构造函数
        vector<int> v1(3);
        // 创建vector对象v2,v2包含5个值为2的元素,调用④构造函数
        vector<int> v2(5,2);
        // 创建vector对象v3,v3包含3个值为1的元素和空间配置器,调用了⑤构造函数
        vector<int> v3(3,1,v2.get_allocator());
        // 创建了vector对象v2的拷贝v4,调用了⑥构造函数
        vector<int> v4(v2);
    
        // 创建一个临时vector对象并对对象元素进行初始化
        vector<int> v5(5);
        for(int index=0;index<5;index++)
        {
            v5[index]=index;
        }
        // 创建vector对象v6,调用⑦构造函数
        vector<int> v6(v5.begin()+1,v5.begin()+2);
        // 输出v1容器元素
        cout<<"v1=";
        for(v1_Iter=v1.begin();v1_Iter!=v1.end();v1_Iter++)
        {
            cout<<" "<<*v1_Iter;
        }
        cout<<endl;
    
        // 输出v2容器元素
        cout<<"v2=";
        for(v2_Iter=v2.begin();v2_Iter!=v2.end();v2_Iter++)
        {
            cout<<" "<<*v2_Iter;
        }
        cout<<endl;
    
        // 输出v3容器元素
        cout<<"v3=";
        for(v3_Iter=v3.begin();v3_Iter!=v3.end();v3_Iter++)
        {
            cout<<" "<<*v3_Iter;
        }
        cout<<endl;
    
        // 输出v1容器元素
        cout<<"v4=";
        for(v4_Iter=v4.begin();v4_Iter!=v4.end();v4_Iter++)
        {
            cout<<" "<<*v4_Iter;
        }
        cout<<endl;
        cout << "v5 =";
        for ( v5_Iter = v5.begin( ) ; v5_Iter != v5.end( ) ; v5_Iter++ )
        {
            cout << " " << *v5_Iter;
        }
        cout << endl;
    
        cout << "v6 =";
        for ( v6_Iter = v6.begin( ) ; v6_Iter != v6.end( ) ; v6_Iter++ )
        {
            cout << " " << *v6_Iter;
        }
        cout << endl;
        // move(v2)返回v2类型即vector类型,v7是通过拷贝构造函数进行创建的
        vector<int> v7(move(v2));
        vector <int>::iterator v7_Iter;
        cout << "v7 =";
        for ( v7_Iter = v7.begin( ) ; v7_Iter != v7.end( ) ; v7_Iter++ )
        {
            cout << " " << *v7_Iter;
        }
        cout << endl;
    }

    上面演示代码运行结果如下图所示:

    2.3 vector元素操作

    vector类中提供了很多成员函数,下面演示下一些常用函数使用,具体演示代码如下:

    #include <vector>
    #include <iostream>
    using namespace std;
    
    void print(vector<int> &v)
    {
        for(size_t i=0;i<v.size();i++)
        {
            cout<<v[i]<<" ";
        }
        cout<<endl;
    }
    
    void main()
    {
        #pragma region 元素的遍历访问
        // 可以采用数组下标、at()函数和迭代器的方式进行遍历访问
        vector<int> vint;
        // 向尾端插入一个元素20
        vint.push_back(20);
        vint.push_back(11);
        vint.push_back(12);
        vint.push_back(25);
        // 使用数组小标方式
        cout<<"vint[1] = "<<vint[1]<<endl;
        for(size_t i=0;i <vint.size();i++)
        {
            // 数组小标访问
            //cout<<"vint["<<i<<"] = "<<vint[i]<<" ";
        
            // 使用at函数访问
            cout<<"vint["<<i<<"] = "<<vint.at(i)<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 利用erase函数删除元素
        // 删除第二个元素,即删除11
        vint.erase(vint.begin()+1);
        cout<<"删除第一个元素后:"<<endl;
        int index1;
        vector<int>::iterator iter; 
        // 使用迭代器访问元素
        for(iter=vint.begin(),index1=0;iter!=vint.end();iter++,index1++)
        {
            cout<<"vint["<<index1<<"] = "<<*iter<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 利用pop_back函数删除尾部元素
        // 调用pop_back删除尾部元素,即删除25
        vint.pop_back();
        cout<<"删除最后一个元素后:"<<endl;
        vector<int>::iterator iter1;
        int j;
        // 使用迭代器访问元素
        for(iter1=vint.begin(),j=0;iter1!=vint.end();iter1++,j++)
        {
            cout<<"vint["<<j<<"] = "<<*iter1<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 反向遍历 vector 的元素
        // 调用inser把元素插入到vector容器中指定位置
        // 插入11到容器中第二个位置
        vint.insert(vint.begin()+1,11);
        // 插入25到容器中最后一个位置,等效于push_back函数
        vint.insert(vint.end(),25);
        vector<int>::iterator iter2;
        int k;
        cout<<"insert两个元素后容器元素为:"<<endl;
        // 使用迭代器访问元素
        for(iter2=vint.begin(),k=0;iter2!=vint.end();iter2++,k++)
        {
            cout<<"vint["<<k<<"] = "<<*iter2<<" ";
        }
        cout<<endl;
        cout<<"反向遍历的结果为:"<<endl;
        vector<int>::reverse_iterator riter;
        int index;
        for( riter=vint.rbegin(),index=0;riter!=vint.rend();riter++,index++)
        {
            cout<<"vint["<<index<<"] = "<<*riter<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 两个vector容器元素的交换
        // 创建vector<int>对象vint2
        vector<int> vint2;
        vint2.push_back(1);
        vint2.push_back(2);
        vint2.push_back(3);
        // 把vint与vint2进行交换
        //swap(vint,vint2);
        vint.swap(vint2);
        cout<<"vint与vint2交换后的结果:"<<endl;
        cout<<"vint = ";
        print(vint);
        cout<<"vint2 = ";
        print(vint2);
        #pragma endregion 
        
    }

    上面代码的运行结果为:

    三、小结

    到这里,本专题的内容介绍结束了,vector向量容器实现为数据线性存储的泛型类,本文介绍了使用数组下标、at()函数和迭代器方式来进行元素访问,然后演示了一些常用函数的使用。vector尾部添加和移除元素效率非常高,但在中部或头部插入元素和删除元素效率较低,这与它的数据结构(线性连续存储方式)有着密切的关系。

  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/zhili/p/STLvector.html
Copyright © 2011-2022 走看看