我将分七次将标准模板库(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;
}
}