STL笔记(2)-vector,迭代器具体用法介绍

时间:2022-12-04 04:24:47

我将分七次将标准模板库(STL)学习笔记的内容整理出来,同时配合源码(几乎每个知识点都会有示例),希望能写得清晰易懂。

STL/string at master · amazingzby/STL · GitHub

本文是第二篇。

STL简介:

STL(Standard Template Library,标准模板库),是由惠普实验室开发的一系列标准化的组件。

STL分为三类:容器(container),迭代器(iterator)和算法(algorithm)。容器和算法通过迭代器可以进行无缝的连接。STL的一个重要特点是数据结构和算法的分离,这种分离使得STL变得非常通用。

本篇介绍STL中容器的概念,以及vector和迭代器的具体用法。



容器:

容器是用来存放,管理一组元素的数据集合。

容器有序列式容器和关联式容器

序列式容器:每个元素的位置取决于元素被插入的时机,被插入时设置的位置,和元素值本身无关。

序列式容器有vector,deque,list

关联式容器:元素位置取决于特定的排序准则,和插入顺序无关。

关联式容器有set,multiset,map,multimap。


vector容器:

vector是将元素置于一个动态数组中加以管理的容器。


vector使用前准备:

#include<vector>

using namespace std;


vector采用模板类实现,vector对象的默认构造形式:vector<T> vecT;

如:

vector<int>veclnt;一个存放int的vector容器

vector<float>vecFloat;一个存放float的vector容器


vector尾部的添加移除操作:

vector.push_back(elem);在容器尾部添加

vector.pop_back();删除最后一个元素


vector数据的存储:

vector有两种形式获取某个索引的值,分别是at和[],比如一个vector vec,取其第5个元素,可以用vec.at(4)或vec[4].

vec.at(idx);返回索引idx所指的数据,如果idx越界,抛出out_of_range异常

vec[idx];返回索引idx所指的数据,越界直接报错

修改:把vec的第5个元素修改为15,两种方式:

vec.at(4)=15;

vec[4]=15;


返回vector的第一个元素和最后一个函数:

vector.front();返回第一个数据

vector.back();返回最后一个数据

修改第一个和最后一个值,例如对于vec:

vec.front()=111;//将vec第一个元素改为111

vec.back()=199;//将vec最后一个元素修改为199


迭代器:

迭代器是一个“可遍历STL容器内全部或部分元素”的对象,迭代器指出容器中的一个特定位置。迭代器就如同一个指针,提供对一个容器中的对象的访问方法,并且可以定义容器中对象的范围。

迭代器种类:

1.输入迭代器,也称“只读迭代器”,它从容器中读取元素,一次读入一个元素向前移动,只支持一遍算法,同一个输入迭代器不能两遍遍历一个序列。

2.输出迭代器,也称“只写迭代器”,一次写入一个元素向前移动,也只支持一遍算法。

3.正向迭代器,组合输入迭代器和输出迭代器的功能,还可以多次解析一个迭代器指定的位置,可以对一个值进行多次读/写。

4.双向迭代器:组合正向迭代器的功能,还可以通过--操作符向后移动位置。

5.随机访问迭代器:组合双向迭代器的功能,可以向前向后跳任意位置,可以直接访问容器中任何位置的元素。


it为迭代器对象

双向迭代器支持的操作:

it++,++it,it--,--it,*it,itA=itB,itA==itB,itA!=itB

其中list,set,multiset,map,multimap支持双向迭代器

随机访问迭代器支持的操作:

在双向迭代器的操作基础上添加:

it+=i,it-=i,it+i(或it=it+i),it[i],itA<itB,itA<=itB,itA>itB,itA>=itB

其中,vector,deque支持随机访问迭代器


vector与迭代器配合使用:

vec.begin()//返回容器第一个元素的迭代器

vec.end();//返回容器最后一个元素之后的迭代器

例如vecInt是vector<int>声明的容器,假设已包含了按顺序的1,3,5,7,9元素

vector<int>::iterator it;//声明容器vector<int>的迭代器

it=vecInt.begin();//此时*it==1

运行++it;//或者it++;,此时*it==3,前++的效率比后++的效率高,前++返回引用,后++返回值


反向迭代器:

vector<int>::reverse_iterator it;声明一个反向迭代器

vec.rbegin();//返回vec中倒数第一个元素的迭代器

vec.rend();//返回容器中倒数最后一个元素之后的迭代器

vector与反向迭代器配合使用:看代码


迭代器其他两种声明方式:

vector<int>::const_iterator

vector<int>::const_reverse_iterator

这两种分别是正向迭代器和反向迭代器的只读形式。使用这两种迭代器时,将不会修改容器中的值。

备注:容器中的insert和erase方法只接受这四种容器中的iterator,其他三种不支持。《Effective STL》建议尽量使用iterator取代其他三种。


vector对象的带参数构造

vector(beg,end);//构造函数将[beg,end)区间中的元素拷贝给本身。区间为左闭右开,即从beg开始到end结束,但不包括end。

vector(n,elem);//构造函数将n个elem拷贝给本身。

vector(const vector &vec);拷贝构造函数。

//见代码举例


vector的赋值

vector.assign(beg,end);//将[beg,end)区间中的数据拷贝赋值给本身。注意该区间和上面一样,是左闭右开的区间。

vector.assign(n,elem);//将n个elem拷贝赋值给本身。

vector & operator=(const vector &vec);//重载等号操作符

vector.swap(vec);//将vec与本身的元素互换


vector的大小

vector.size();//返回容器中元素的个数

vector.empty();//判断容器是否为空

vector.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则尾部超出容器长度的元素被删除。

vector.resize(num,elem);//重新指定容器长度为num,变长则以elem值填充新位置;变短则超出元素被删除。


vector的插入

vector.insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置

vector.insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值

vector.insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。


vector的删除:

vector.clear();移除容器的所有数据

vector.erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。

vector.erase(pos);//删除pos位置的数据,返回下一个数据的位置

例子:删除所有3

int iArray[]={1,3,2,3,3,3,4,3,5,3};

vector<int>vecInt(iArray,iArray+10);

for(vector<int>::iterator it=vecInt.begin();it !=vecInt.end();)//小括号不需要写++it

{

    if(*it==3)

    {

        it=vecInt.erase(it);//以迭代器为参数,删除元素3,并把数据删除后的下一个元素位置作为返回值

        //此时,不执行++it;

    }

    else

    {

        ++it;

    }

}