后台开发:核心技术与应用实践3.3.2 vector的查增删

    xiaoxiao2024-01-16  159

    3.3.2 vector的查增删

    1.?vector的初始化和遍历

    vector的初始化方法如表3-1所示。

    表3-1 vector的各种初始化方法

    vector<T> v1    v1是一个空vector,它潜在的元素是T类型的,执行默认初始化

    vector<T> v2(v1)    v2中包含有v1所有元素的副本

    vector<T> v2 = v1  等价于v2(v1),v2中包含有v1所有元素的副本

    vector<T> v3(n, val)     v3包含了n个重复的元素,每个元素的值都是val

    vector<T> v4(n)     v4包含了n个重复地执行了值初始化的对象

    vector<T> v5{a,b,c...}  v5包含了初始值个数的元素,每个元素被赋予相应的初始值

    vector<T> v5={a,b,c...}      等价于v5{a,b,c...}

     

    vector的遍历有for(int i=0;i<a.size();++i)、for (iter=ivector.begin();iter!=ivector.end();iter++)、for_each这几种方式。

    【例3.8】 vector的初始化和遍历。

    #include <vector>

    #include <iostream>

    using namespace std;

    int main(){

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

        vector<int> ivector(a,a+7);

        /*vector的赋值并不可以像数组一样用花括号方便地完成赋值,这里借用了数组来初始化这个vector

          初始化方式vector<elementType> intvec(begin,end);这样可以用起来看上去还是比较习惯的。*/

        vector<int>::iterator iter;

        for (iter=ivector.begin();iter!=ivector.end();iter++){

            cout<<*iter<<" ";

        }

        cout<<endl;

        ivector[5]=1;

        /*单个vector的赋值,这个方式看上去还是和数组一样的也可以这么写ivector.at(5)=1;但是

          就是不习惯*/

        cout<<ivector[5]<<endl<<ivector.size()<<endl;

        for (iter=ivector.begin();iter!=ivector.end();iter++){

            cout<<*iter<<" ";

        }

        cout<<endl;

        for(int i=0;i<5;i++){

            cout<<ivector[i]<<" ";

        }

        cout<<endl;

        return 0;

    }

    程序的执行结果是:

    1 2 3 4 5 6 7

    1

    7

    1 2 3 4 5 1 7

    1 2 3 4 5

    例3.8中展示了for(int i=0;i<a.size();++i)、for (iter=ivector.begin();iter!=ivector.end();iter++)的遍历方式,vector中也可以直接用ivector[i]的方式访问第i个元素。

    【例3.9】 for_each的遍历举例。

    #include <vector>

    #include <algorithm>

    #include <iostream>

    using namespace std;

     

    void print(int n)

    {

        cout<<n<<" ";

    }

     

    int main(){

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

        vector<int> ivector(a,a+7);

        vector<int>::iterator iter;

        for_each(ivector.begin(),ivector.end(),print);// 用for_each进行遍历

        cout<<endl;

        ivector[5]=1;

        cout<<ivector[5]<<endl<<ivector.size()<<endl;

        for_each(ivector.begin(),ivector.end(),print);// 用for_each进行遍历

        return 0;

    }

    程序的执行结果为:

    1 2 3 4 5 6 7

    1

    7

    1 2 3 4 5 1 7

    例3.9中展示了如何使用for_each遍历vector中的元素。

    vector是个模板类,可以存放任何类型的对象。在vector中存放结构体时,可以按照自定义的排序方式排序。

    【例3.10】 vector中存放结构体时的排序。

    #include<algorithm>

    #include<vector>

    #include<iostream>

    using namespace std;

     

    typedef struct rect{

        int id;

        int length;

        int width;

        bool operator< (const rect &a) const{

            if(id!=a.id)

                return id<a.id;

            else{

                if(length!=a.length)

                    return length<a.length;

                else

                    return width<a.width;

            }

        }

    }Rect;

     

    int main(){

        vector<Rect> vec;

        Rect rect;

        rect.id=2;

        rect.length=3;

        rect.width=4;

        vec.push_back(rect);

        rect.id=1;

        rect.length=2;

        rect.width=3;

        vec.push_back(rect);

        vector<Rect>::iterator it=vec.begin();

        cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;

        sort(vec.begin(),vec.end());

        cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;

        return 0;

    }

    程序的执行结果是:

    2 3 4

    1 2 3

    例3.10中,vec中存放的是结构体Rect。vec未进行排序前,将会按照push_back的时间顺序排序,并不会自动排序。排序后,可以按照结构体中对rect的重载方式进行排序:按照id、length、width升序排序,然后用<algorithm>中的sort函数排序。

    除了重载结构体里的rect,也可以在结构体外定义一个函数来进行比较。

    【例3.11】 结构体外定义比较函数。

    #include<algorithm>

    #include<vector>

    #include<iostream>

    using namespace std;

     

    typedef struct rect{

        int id;

        int length;

        int width;

    }Rect;

    int cmp(Rect a,Rect b){

        if(a.id!=b.id)

                    return a.id<b.id;

        else{

                    if(a.length!=b.length)

                return a.length<b.length;

            else

                return a.width<b.width;

        }

    }

     

    int main(){

        vector<Rect> vec;

        Rect rect;

        rect.id=2;

        rect.length=3;

        rect.width=4;

        vec.push_back(rect);

        rect.id=1;

        rect.length=2;

        rect.width=3;

        vec.push_back(rect);

        vector<Rect>::iterator it=vec.begin();

        cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;

        sort(vec.begin(),vec.end(),cmp);

        cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;

        return 0;

    }

    程序的执行结果是:

    2 3 4

    1 2 3

    例3.11与例3.10不同的地方是,例3.11中并没有对结构体进行重载,而是在结构体外定义了一个比较函数;另外sort的调用方式也不相同,例3.11中加了个比较函数作为第3个参数。二者均可以实现对vec的排序。

    2.?vector的查找

    在vector中查找一个元素可以如例3.12所示。

    【例3.12】 在vector中查找元素。

    #include<algorithm>

    #include<vector>

    #include<iostream>

    using namespace std;

    int main(){

        vector<int> vec;

        vec.push_back(1);

        vec.push_back(2);

        vec.push_back(3);

        vec.push_back(4);

        vec.push_back(5);

        vector<int>::iterator iter=find(vec.begin(),vec.end(),3);

        if ( iter==vec.end())

            cout << "Not found" << endl;

        else

            cout << "Found" << endl;

        return 0;

    }

    程序的执行结果是:

    Found

    例3.12中,使用了f?ind函数在vector中进行查找。注意f?ind函数不属于vector的成员,而存在于算法中,所以应加上头文件#include <algorithm>。

    3.?vector的删除

    vector中的删除,可以有erase或pop_back函数。erase可以删除指定元素或指定位置的元素,而pop_back只能去掉数组的最后一个数据。

    erase的函数原型有以下两种形式:

    iterator erase(iterator position)。

    iterator erase(iterator first, iterator last)。

    假设有这样的程序:

    vector<int> vec;

    vec.push_back(1);

    vec.push_back(2);

    vec.push_back(3);

    vec.push_back(4);

    vec.push_back(5);

    for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); iter++){

        if( *iter == 3)

            veci.erase(iter);

    }

    乍一看这段代码很正常,其实这里面隐藏着一个很严重的错误:当veci.erase(iter)语句执行了之后,iter就变成了一个野指针,对一个野指针进行iter++操作是肯定会出错的。

    查看MSDN,对于erase的返回值是这样描述的:An iterator that designates the f?irst element remaining beyond any elements removed, or a pointer to the end of the vector if no such element exists,于是改代码:

    for(vector<int>::iterator iter=vec.begin(); iter!=vec.end(); iter++){

        if( *iter == 3)

            iter = vec.erase(iter);

    }

    这段代码也是错误的:①无法删除两个连续的3;②当数字3位于vector最后位置的时候,也会出错(在vec.end()上执行++操作)。正确的代码应如例3.13所示。

    【例3.13】 使用erase删除vector中某个元素。

    #include<algorithm>

    #include<vector>

    #include<iostream>

    using namespace std;

    int main(){

        vector<int> vec;

        vec.push_back(1);

        vec.push_back(2);

        vec.push_back(3);

        vec.push_back(4);

        vec.push_back(5);

        vector<int>::iterator iter=vec.begin();

        for(;iter!=vec.end();){

            if(*iter==3){

                iter=vec.erase(iter);

            }else{

                ++iter;

            }

        }

        for(iter=vec.begin();iter!=vec.end();iter++){

                    cout<<*iter<<" ";

        }

        return 0;

    }

    程序的执行结果是:

    1 2 4 5

    例3.13中,for语句条件里面删除元素时,返回值指向已删除元素的下一个位置,不是删除元素时则直接进行++操作。

    使用vec.erase(vec.begin()+i,vec.end()+j)语句则是删除区间[i,j-1]间的元素。

    而pop_back只能去掉数组的最后一个数据。

    【例3.14】 vector的pop_back函数使用举例。

    #include<algorithm>

    #include<vector>

    #include<iostream>

    using namespace std;

    int main(){

        vector<int> vec;

        for(int i=0;i<10;i++)

            vec.push_back(i);

        vector<int>::iterator iter=vec.begin();

        for(iter=vec.begin();iter!=vec.end();iter++){

            cout<<*iter<<" ";

        }

        cout<<endl;

        vec.pop_back();

        for(iter=vec.begin();iter!=vec.end();iter++){

            cout<<*iter<<" ";

        }

        cout<<endl;     

        return 0;

    }

    程序的执行结果是:

    0 1 2 3 4 5 6 7 8 9

    0 1 2 3 4 5 6 7 8

    例3.14中定义了一个存放整型数的vector,里面存放了0~9。用pop_back函数,则把最晚进入vector的9删除。

    4.?vector的增加

    vector中的增加,可以有insert和push_back。insert是插入元素到某个位置中,push_back是在最后添加一个元素。

    insert的函数原型有以下3种形式:

    iterator insert( iterator loc, const TYPE &val );

               // 在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器

    void insert( iterator loc, size_type num, const TYPE &val );

               // 在指定位置loc前插入num个值为val的元素

    void insert( iterator loc, input_iterator start, input_iterator end );

               // 在指定位置loc前插入区间[start, end)的所有元素

    【例3.15】 vector的查增删用法举例。

    #include<algorithm>

    #include<vector>

    #include<iostream>

    using namespace std;

    void print( vector<int>v ){

        vector<int>::iterator iter=v.begin();

        for(;iter!=v.end();iter++)

            cout<<*iter<<" ";

        cout<<endl;

    }

    int main(){

        vector<int> v;              // 现在容器中有0个元素

        int values[] = {1,3,5,7};

        v.insert(v.end(), values+1, values+3);     // 现在容器中有2个元素分别为:3,5

        print(v);

        v.push_back(9);            // 现在容器中有3个元素分别为:3,5,9

        print(v);

        v.erase(v.begin()+1);                // 现在容器中有2个元素分别为:3,9

        print(v);

        v.insert(v.begin()+1, 4);      // 现在容器中有3个元素分别为:3,4,9

        print(v);

        v.insert(v.end()-1, 4, 6);      // 现在容器中有7个元素分别为:3,4,6,6,6,6,9

        print(v);

        v.erase(v.begin()+1, v.begin()+3);   // 现在容器中有5个元素分别为:3,6,6,6,9

        print(v);

        v.pop_back();                    // 现在容器中有4个元素分别为:3,6,6,6

        print(v);

        v.clear();                     // 现在容器中有0个元素

        print(v);

        if (true == v.empty())         // 如果容器为空则输出“null”

        {

            std::cout<<"null"<<std::endl;

        }

        return 0;

    }

    例3.15的程序的执行结果如图3-1所示。

    例3.15中的语句:

    v.insert(v.end(), values+1, values+3);

    就是将数组第2个元素和第3个元素的值插入到v.end()位置中,因为此时v还是空的,所以也就是往空vector里插入了两个元素。注意,这里只插入了两个元素,而没有插入3个元素。

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

    v.begin()是指第1个元素,那v.begin()+1就是指第2个元素,即这里是删除第2个元素。

    v.insert(v.end()-1, 4, 6);

    v.end()是指最后一个元素的下一个位置,v.end()-1就是倒数第2个元素的前面一个位置,插入4个6,因此结果是3 4 6 6 6 6 9。

    程序中v.clear()表示将v清空;v.empty()表示判断vector是否为空,如果为空,则返回true。

    相关资源:C#高级编程(第9版)包括源码
    最新回复(0)