参考:http://www.weixueyuan.net/view/6402.html

总结:

  vector可以理解为可以在两端插入、删除数据的数组,它提供了丰富的成员函数,用于操作数据。

    begin()返回的是一个迭代器,如果容器不为空,则返回的迭代器指向容器的第一个元素;如果容器为空,则返回的迭代器指向容器尾部之后的位置。

    end()函数同样返回的是一个迭代器,该迭代器指向的是容器尾部之后的位置。当容器为空时,begin()函数和end()函数都指向同一个位置。

    调用insert函数时,如果不是在容器尾部插入元素,则需要将所插入位置以后的元素都向后移一位,然后再将需要插入的元素插入到当前位置。

    erase函数删除容器中的元素

  vector和deque不同。vector说到底是个数组,在非尾部插入元素都需要移动其它元素,

  而deque则不同,它是一个可以操作数组头部和尾部的数组,因此在头部或尾部插入或删除数据,其处理效率都是一样的。

  当我们需要频繁在头部和尾部插入或删除数据,则deque优于vector。

  通常每定义一个容器,就会有一个与容器数据类型相关的迭代器。

  如果我们不需要修改容器中的元素,仅仅只是进行访问的话,则可以定义为const_iterator。

  当我们需要获得当前迭代器所指的元素时,我们可以用取址操作符“*”来操作迭代器,“*iter”就为迭代器所指向的元素。

  list并没有重载下标操作符,因而不能根据下标进行直接访问。

  list容器是一个双向链表,因此在容器中的任何位置插入元素,都不需要移动其它元素,因此执行效率是稳定的。

------------------

我们以vector、deque和list为例介绍基本序列式容器。我们先来看一个关于vector的例子。

例1:

#include <iostream>
#include <vector>
using namespace std; int main()
{
vector< int > num;
num.push_back( );
num.insert(num.begin(), );
num.insert(num.end(), );
num.push_back( );
num.push_back( );
cout << num.size() << endl;
for(int i = ; i < num.size(); i++)
cout << num[i] << " ";
cout << endl;
num.erase(num.begin());
cout << num.size() << endl;
for(int i = ; i < num.size(); i++)
cout<< num[i] <<" ";
cout << endl;
return ;
}

vector可以理解为可以在两端插入、删除数据的数组,它提供了丰富的成员函数,用于操作数据。在本例中我们加入了头文件vector,在使用vector时必须包含该头文件。

我们接着来看一下主函数。在主函数中我们定义了一个vector类的int型实例num,需要注意的是我们并没有指定实例的大小,因为vector是可以根据需求自动调整大小的,这一点跟数组不同。接下来我们调用函数push_back,该函数时在vector实例num的最后添加一个元素,因为一开始定义的时候为空,因此此时的num中只包含一个元素50。

之后我们再调用insert函数,该函数可以在指定位置插入元素。在insert参数中,我们分别调用了begin和end函数,这两个函数分别用来访问num实例的头部和尾部。begin()返回的是一个迭代器,如果容器不为空,则返回的迭代器指向容器的第一个元素;如果容器为空,则返回的迭代器指向容器尾部之后的位置。end()函数同样返回的是一个迭代器,该迭代器指向的是容器尾部之后的位置。当容器为空时,begin()函数和end()函数都指向同一个位置,当容器有一个元素的时候,begin()函数指向第一个元素的位置,end()函数则指向第一个元素之后的位置。调用insert函数时,如果不是在容器尾部插入元素,则需要将所插入位置以后的元素都向后移一位,然后再将需要插入的元素插入到当前位置。例如我们要在开头插入一个元素,则需要将容器现有的元素都向后移动一个位置,然后再将元素插入到第一个位置,因此vector在非尾部位置插入元素,其效率不高。在主函数中调用两次insert函数之后,此时的容器num中的元素有:10,50,20。

之后又调用了两个push_back函数,在容器尾部插入了两次数据。此时容器中的数据按顺序依次为:10,50,20,60,40。

之后调用size函数,返回容器的大小,因为此时容器中包含五个元素,因此返回值为5。接下来我们将容器中的元素一一打印出来,我们可以通过下标操作符访问容器中的元素,打印结果为:10,50,20,60,40。

接下来调用erase函数删除容器中的元素,删除位置是容器第一个元素,删除之后,该位置就会空出,此时后面的元素需要全部向前移动一个位置。此时容器中的元素按顺序一次为:50,20,60,40。

例2:

#include <iostream>
#include <deque>
using namespace std; int main()
{
deque< int > num;
num.push_back();
num.insert(num.begin(), );
num.insert(num.end(), );
num.push_back();
num.push_back();
cout<<num.size()<<endl;
for(int i=; i < num.size(); i++)
cout<<num[i]<<" ";
cout<<endl;
num.erase(num.begin());
cout<<num.size()<<endl;
for(int i=; i < num.size(); i++)
cout<<num[i]<<" ";
cout<<endl;
return ;
}

我们将例1中的vector换成deque,运行程序我们发现两个程序的运行结果完全相同。是不是vector和deque相同呢?其实不是的,vector说到底是个数组,在非尾部插入元素都需要移动其它元素,而deque则不同,它是一个可以操作数组头部和尾部的数组,因此在头部或尾部插入或删除数据,其处理效率都是一样的。当我们需要频繁在头部和尾部插入或删除数据,则deque优于vector。

例3:

#include <iostream>
#include <string>
#include <list>
using namespace std; int main()
{
list< string > str;
str.insert( str.begin(), "A" );
str.insert( str.begin(), "B" );
str.insert( str.end(), "C" );
str.insert( str.end(), "D" );
str.insert( str.begin(), "E" );
str.insert( str.begin(), "F" );
list< string >::iterator iter;
for(iter = str.begin(); iter != str.end(); iter++)
cout<< * iter <<endl;
str.reverse();
for(iter = str.begin(); iter != str.end(); iter++)
cout<< * iter <<endl;
return ;
}

在本例中我们定义了一个list容器string类型的实例str,之后我们先在容器中添加了6个string类型元素,为了遍历str容器,我们定义了一个迭代器iter。通常每定义一个容器,就会有一个与容器数据类型相关的迭代器,本例中定义了容器str,则它的对应的容器有:

list < string >::iterator
list< string >::const_iterator

如果我们不需要修改容器中的元素,仅仅只是进行访问的话,则可以定义为const_iterator。

为了从头到尾遍历容器,我们先将迭代器指向str.begin(),for循环的结束条件是str.end(),每次运行一遍循环体中的内容,迭代器自增一次,相当于指向下一个元素,我们之所以能够直接使用自增运算符,那是因为在容器的类中系统已经重载过了自增操作符。当我们需要获得当前迭代器所指的元素时,我们可以用取址操作符“*”来操作迭代器,“*iter”就为迭代器所指向的元素。在此程序中我们之所以没有按照vector和deque的方式,以下标进行访问容器中的元素,那是因为list并没有重载下标操作符,因而不能根据下标进行直接访问。

在主函数中我们调用了reverse函数,对容器中的元素进行翻转,然后再次打印容器中的元素。

list容器是一个双向链表,因此在容器中的任何位置插入元素,都不需要移动其它元素,因此执行效率是稳定的。

7.5 C++基本序列式容器的更多相关文章

  1. STL源码剖析读书笔记--第四章--序列式容器

    1.什么是序列式容器?什么是关联式容器? 书上给出的解释是,序列式容器中的元素是可序的(可理解为可以按序索引,不管这个索引是像数组一样的随机索引,还是像链表一样的顺序索引),但是元素值在索引顺序的方向 ...

  2. STL源码剖析之序列式容器

    最近由于找工作需要,准备深入学习一下STL源码,我看的是侯捷所著的<STL源码剖析>.之所以看这本书主要是由于我过去曾经接触过一些台湾人,我一直觉得台湾人非常不错(这里不涉及任何政治,仅限 ...

  3. STL序列式容器学习总结

    STL序列式容器学习总结 参考资料:<STL源码剖析> 参考网址: Vector: http://www.cnblogs.com/zhonghuasong/p/5975979.html L ...

  4. STL——序列式容器

    一.容器概述与分类 1. STL容器即是将运用最广的一些数据结构实现出来.常用的数据结构有array, list, tree, stack, queue, hash table, set, map…… ...

  5. STL学习笔记(序列式容器)

    Vector Vector是一个动态数组. 1.Vector的操作函数 构造.拷贝和析构 vector<Elem> c //产生一个空vector ,其中没有任何元素 vector< ...

  6. vector是序列式容器而set是关联式容器。set包含0个或多个不重复不排序的元素。

    1.vector是序列式容器而set是关联式容器.set包含0个或多个不重复不排序的元素.也就是说set能够保证它里面所有的元素都是不重复的.另外对set容器进行插入时可以指定插入位置或者不指定插入位 ...

  7. STL源码剖析——序列式容器#1 Vector

    在学完了Allocator.Iterator和Traits编程之后,我们终于可以进入STL的容器内部一探究竟了.STL的容器分为序列式容器和关联式容器,何为序列式容器呢?就是容器内的元素是可序的,但未 ...

  8. 数据结构-STL序列式容器总结

    根据序列在容器中的排列特性,将常见数据结构分为:序列式容器和关联式容器. 常见序列式容器有 1.array(build-in)c++內建 2.vector 3.heap(以算法方式呈现) 4.prio ...

  9. STL源码剖析:序列式容器

    前言 容器,置物之所也.就是存放数据的地方. array(数组).list(串行).tree(树).stack(堆栈).queue(队列).hash table(杂凑表).set(集合).map(映像 ...

随机推荐

  1. Mongodb 分享(一)

    Mongodb使用基础知识: 一.简介 1.mongodb是什么? 1)MongoDB 是一个基于分布式文件存储的数据库.由 )mongodb 客户端:NoSQL Manager for MongoD ...

  2. Getting started with Processing 第十三章——延伸(1)

    导入库: 导入库的名称为:import processing.libName.* 声音 播放声音 支持的格式:wav,aiff,mp3声明: SoundFile blip;创建:blip = new ...

  3. 当实体类中entity/DTO/VO等类中,有枚举值,应该怎么输出?

    当实体类中entity/DTO/VO等类中,有枚举值,应该怎么输出? 问题: orderStatus 和 payStatus都是枚举类,并且枚举的个数达地10来个,我们不可能在模板页面(jsp/ftl ...

  4. 如何跳过开机密码进入windows系统

    工具:安装好PE系统的u盘一个. 开机时按F12(每个电脑不同)进入PE系统,将c盘目录下的SAM文件拷入自己的u盘内.SAM文件的位置:  C:\WINDOWS\system32\config\SA ...

  5. codeforces708b// Recover the String //AIM Tech Round 3 (Div. 1)

    题意:有一个01组成的串,告知所有长度为2的子序列中,即00,01,10,11,的个数a,b,c,d.输出一种可能的串. 先求串中0,1的数目x,y. 首先,如果00的个数a不是0的话,设串中有x个0 ...

  6. P5157 [USACO18DEC]The Cow Gathering

    首先考虑怎么check一个点是否能被最后一个删除. 可以这么建图,以这个点建有根树,边全部向上指,再加上剩下的有向边. 很明显,这里的一条边的定义就变成了只有删去这个点,才可以删去它指向的点. 因此, ...

  7. python-django rest framework框架之解析器

    1.解析器 : 对请求的数据进行解析 - 请求体进行解析. 解析器在你不拿请求体数据时 不会调用. class UsersView(APIView): def get(self,request,*ar ...

  8. Centos7 JDK安装过程中 解决java -version 报错: bash: /home/jdk1.8.0_161/bin/java: Permission denied

    1.执行Linux命令 -----vim /etc/profile  编辑profile  文件,在里面添加: #set java enviroment JAVA_HOME=/opt/JavaHome ...

  9. Leetcode 1002. 查找常用字符

    1002. 查找常用字符  显示英文描述 我的提交返回竞赛   用户通过次数301 用户尝试次数324 通过次数303 提交次数480 题目难度Easy 给定仅有小写字母组成的字符串数组 A,返回列表 ...

  10. img 标签

    设计网页时经常使用的图片有三种,它们的相同点是都经过了压缩,压缩比越高,图像品质越差. GIF(Graphics Interchange Format):最多支持256色,支持透明,支持多帧动画显示效 ...