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

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。

时间: 2024-10-25 00:32:45

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

后台开发:核心技术与应用实践

后台开发:核心技术与应用实践 徐晓鑫 著 图书在版编目(CIP)数据 后台开发:核心技术与应用实践 / 徐晓鑫著. -北京:机械工业出版社,2016.8 ISBN 978-7-111-54339-8 I. 后- II. 徐- III. 网络-开发 IV. TP393.092 中国版本图书馆CIP数据核字(2016)第167884号 后台开发:核心技术与应用实践 出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037) 责任编辑:李 艺 责任校对:董纪丽 印 刷: 版 次:

后台开发:核心技术与应用实践导读

后台开发:核心技术与应用实践 徐晓鑫 著 图书在版编目(CIP)数据 后台开发:核心技术与应用实践 / 徐晓鑫著. -北京:机械工业出版社,2016.8 ISBN 978-7-111-54339-8 I. 后- II. 徐- III. 网络-开发 IV. TP393.092 中国版本图书馆CIP数据核字(2016)第167884号 后台开发:核心技术与应用实践 出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037) 责任编辑:李 艺 责任校对:董纪丽 印 刷: 版 次:

Android开发:优化ListView实践解析

 在看了一些vogella的文章之后,发现关于android listview性能优化这一段很有意思,于是实践了一下,经过优化,性能确实提升不少! 先看看优化前和优化后的比较: 优化前的log截图: 开发:优化ListView实践解析-"> 优化后的log截图: 并且,在不停滚动ListView的过程中,优化之前会出现ANR现象,在AVD上特别容易复现: 然后,优化后显得很流畅,附上对于的log截图: 下面附上相关代码分析: ListView中的每一个Item由一个ImageView 和一

android-Android后台开发相关书籍资料

问题描述 Android后台开发相关书籍资料 Android APP后台搭建过程,如何使用开发语言实现,请推荐相关书籍,谢谢. 解决方案 <第一行代码> <疯狂Android讲义> <Android群英传> <Android开发艺术探究> 解决方案二: 后台开发相关书籍Android各层开发推荐书籍及资料(转)Android相关开发资料汇总 解决方案三: http://www.jikexueyuan.com/course/2208.html 解决方案四: 深

mysql-app后台开发,如何做好安全性?

问题描述 app后台开发,如何做好安全性? app后台开发一枚,现在要对整个项目做一些安全性,比如拦截非法请求,sql注入什么的 后台开发技术:spring + mybatis + mysql 求一些思路.麻烦了. 解决方案 比如检查密码的sql语句一定要处理特殊字符? = ' 等等,最后还是要写file.将你所设想到的情况全写下来.后期安全还有问题再添加. 解决方案二: 最好安卓请求时要带上自己的用户信息 解决方案三: 接口的话,多加一些加密处理了,然后在登录的时候带token,再就是服务器的

linux 后台开发-后台开发需要些什么东西

问题描述 后台开发需要些什么东西 我是一名大三的学生,想做后台开发,但是又不知道该从哪方面做起.目前Linux c/c++都学的不错,数据结构也学过,SQL.socket网络通信也学过,TCP/IP协议也有一定了解,然后,下一步不知道该干嘛了,我觉得自己学的这些东西比较基础,都不知道怎么怎么能把它们应用实际.望各位大牛能指点迷津 解决方案 这看你想做哪方面的了.linux服务器开发维护,数据库开发维护,网站后台web开发(javawebphp.net等) 解决方案二: 你所学的仅仅是基础,多看看

Linux 后台开发工作中常用的开源库

后台开发,语言主要是 c 和 c++ , 这里简单罗列一下工作中用的很频繁的那些开源软件 1. OpenSSL openssl OpenSSL 是一个安全套接字层密码库,囊括主要的密码算法.常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用. 下载地址: https://www.openssl.org/source/ 2.TinyXML tinyxml 简单,高效,灵活的一套操作 XML 文件的开源库. 下载地址: http://www.grinninglizar

javascript-App后台开发用哪种语言

问题描述 App后台开发用哪种语言 我想问开发一个APP的后台,想实现的功能有实时聊天,图片,视频的上传和下载等, 用java写好,还是其他的好 解决方案 java.php.python.c++.....很多,建议使用java,轮子多,效率高,也可以用python,简单,效率也不低 解决方案二: 后台有很多选择,如果你熟悉android,那么当然选java,那是你熟悉的语言,如果你熟悉js,可以用node.js,其它的语言还有C# VB PHP Ruby Python Go ... 解决方案三:

ios-iOS APP后台开发技术问题请教

问题描述 iOS APP后台开发技术问题请教 如果要搭建一个IOS应用(假设用户量为几十万)的后台服务器,现在比较靠谱的后台架构是怎样的? (先说说我现在的理解,之前做过一些Android开发的事情,当时后台是写了一个简单的Http服务器(利用Netty实现),然后前端和后台的数据交换采用json实现,至于服务器硬件的配置等等没有过考虑.所以我现在可以认识到的后台,就是HTTP请求+Json返回数据.) 想请教一下各位:从服务器硬件到操作系统再到后台技术框架,有没有一个比较系统.成熟.可靠的模式