STL概述
说到STL我们往往认为它是基于模板的,实现了很多数据结构及对应操作的容器库。
从概念上像上面理解一样理解没有问题,从库的内部结构来看,STL主要由container(容器),algorithm(算法)和iterator(迭代器)三大部分构成。
STL容器
容器就是指给你在库的内部已经实现好,可以让你直接调用的基于模板的数据结构类型,用于存放数据对象(元素)。常用的数据结构和相对应的头文件如下:
| 数据结构 | 说明 | 实现头文件(自行补充双箭头) |
|---|---|---|
| 向量(vector) | 以数组为底层数据结构的连续存储元素容器,支持随机访问 | vector |
| 字符串(string) | 字符串处理容器 | string |
| 双端队列(deque) | 连续存储的指向不同元素的指针所组成的指针数组。底层数据结构为一个中央控制器和多个缓冲区,支持首尾元素(中间不能)快速增删和访问,也支持随机访问 | deque |
| 链表(list) | 由结点组成的链表,每个结点包含着一个元素。底层数据结构为双向链表,支持结点的快速增删 | list |
| 栈(stack) | 后进先出的序列。底层一般用deque(默认)或者list实现 | stack |
| 队列(queue) | 先进先出的序列。底层一般用deque(默认)或者list实现 | queue |
| 优先队列(priority_queue) | 元素的进出队顺序由关系函数决定的一种队列。底层数据结构一般为vector(默认)或者deque | queue |
| 集合(set)/多重集合(multiset) | 由结点组成的红黑树,每个结点都包含着一个元素,set中所有元素有序但不重复,multiset中所有关键字有序但不重复 | set |
| 映射(map)/多重映射(multimap) | 由(关键字,值)构成的对(pair)组成的集合,底层数据结构为红黑树,map中所有关键字有序但不重复,multimap中所有关键字有序但可以重复 | map |
STL算法
STL算法用于操作容器中的数据对象,即数据结构的对应操作,例如find(),sort()等,且由于STL容器是基于模板设计的,STL算法一般具有很好的通用性和灵活性,具体内容这里不多赘述。
尽管各种STL容器的内部结构并不是完全相同,但他们外部的一些框架都是类似的,例如线性结构;对数据操作也是类似的,例如访问第一个元素,清空所有的元素,求容器内存在有效元素的元素个数,将容器内的元素进行排序。
于是可以将对于STL容器的一些操作设计成通用在各个容器的STL算法,也就是说对于一些通用的操作(STL算法),它们不再是某些STL容器自己的操作,而是独立出STL容器的通用算法,这些通用的STL算法就与STL容器分离开来了。
STL算法部分主要由头文件< algorithm >,< numeric >和< functional >组成。
STL迭代器
由于大量的通用STL算法与STL容器分离开,我们在对容器内的数据进行操作时,需要一个将算法与容器连接起来的桥梁(中介),STL迭代器在STL中就起到前两这样的作用。
迭代器的使用方式和指针非常类似:可以用迭代器加*去访问容器中的数据对象,每个容器都有自己的迭代器,算法通过迭代器来定位和操作容器中的元素(类似于函数以指针作为参数传递数据),指针中++,–的运算符在迭代器中的用法和指针是一样的。
不过迭代器绝不是指针,它只是一个仿照指针的使用方式封装起来的类。
常见的迭代器如下
iterator:指向容器中存放元素的迭代器,用于正向遍历容器中的元素。
const_iterator:指向容器中存放元素的常量迭代器,只能读取容器中的元素。
reverse_iterator:指向容器中存放元素的反向迭代器,用于反向遍历容器中的元素。
const_reverse_iterator:指向容器中存放元素的常量反向迭代器,只能读取容器中的元素。
容器,算法,迭代器三者的关系如下图所示:

常用的STL容器
每个STL容器都是一个类模板,从数据元素按照什么样的逻辑关系存储到容器中分为顺序容器和关联容器(适配器容器是指基于其他容器实现的容器,也就是说适配器容器包含另一个容器作为其底层容器,在底层容器的基础上实现适配器容器的功能,在算法设计中可以将适配器容器作为一般容器来使用,所以我们这里不把它单独地分为一类)。
vector(向量容器)
向量容器用于存储具有相同数据类型的一组元素,相当于不固定长度的数组,如果初始分配的空间不够,当超过空间大小时会重新分配更大的空间(就是我们在另一个专栏提到的扩容的操作,扩容通常按照两倍的大小进行扩展,具体原因见另专栏)。
可以从末尾快速的插入与删除元素,快速地随机访问元素,但是在序列中间插入、删除元素较慢,因为需要移动插入或删除处后面的所有元素。
定义vector容器的几种方式如下:
//定义元素为int的向量
v1vector<int>v1;
//指定向量v2的初始大小为10个int元素
vector<int>v2(10);
//指定v3的10个初始double元素的初值为1.23
vector<double> v3(10,1.23);
//用数组a的5个元素初始化v4
vector<int>v4(a,a+5);
vector的成员函数及其功能如下:
容器名.empty():判断当前向量容器是否为空。
容器名.size():返回当前向量容器的中的实际元素个数。
容器名[]:返回指定下标的元素。
容器名.reserve(n):为当前向量容器预分配n个元素的存储空间。
容器名.capacity():返回当前向量容器在重新进行内存分配以前所能容纳的元素个数。
容器名.resize(n) :调整当前向量容器的大小,使其能容纳n个元素。
(resize的功能较为复杂,如果当前向量容器的大小大于n,相当于截去第n个元素后面的元素;如果当前向量的大小小于n,相当于补充了若干个相同的元素)
容器名.push_back(elem):在当前向量容器尾部添加了一个元素elem。
(同理有一个删除尾部元素的操作为pop_back,用法相同)
容器名.insert(pos,elem):在pos位置插入元素elem,即将元素elem插入到迭代器pos指定元素之前。
容器名.front():获取当前向量容器的第一个元素。
容器名.back():获取当前向量容器的最后一个元素。
容器名.erase(pos),容器名.erase(pos1,pos2):删除当前向量容器中某个迭代器或者迭代器区间指定的元素。
容器名.clear():删除当前向量容器中所有元素(但是不清空内存)。
容器名.begin():返回iterator或const_iterator,引用容器的第一个元素。
容器名.end():返回iterator或const_iterator,引用容器的最后一个元素的后面一个元素。
(end()不指向容器内的任何一个存在的元素,指向最后一个元素的下一个元素)
容器名.rbegin():返回reverse_iterator或const_reverse_iterator,引用容器的最后一个元素。
容器名.rend():返回reverse_iterator或const_reverse_iterator,引用容器的第一个元素的前面一个元素。
string(字符串容器)
string是一个保存字符序列的容器,所有元素为字符类型,类似vector< char >(char数组,但各操作的效率都低于char数组,char指针数组,很多库的函数的参数都固定要求是char指针数组的指针变量而不是string变量)。
除了有字符串的一些常用操作以外,还有包含了所有的序列容器的操作。字符串的常用操作包括增加,删除,修改,查找比较,连接,输入,输出等(就是说重载了+,-,>,<,+=,-=,<<,>>等很多运算符)。
创建string容器的几种方式如下:
//创建char数组cstr
char cstr[]="China! Greate Wall";
//用char数组cstr创建string类字符串s1
string s1(cstr);
//用string类字符串s1创建string类字符串s2
string s2(s1);
//截取char数组pos1到pos2之间的片段创建string类字符串s3
string s3(cstr,pos1,pos2);
//从第0位开始从char数组cstr截取n个字符创建string类字符串s4
string s4(cstr,n);
//以连续n个字符x创建string类字符串s5
string s5(n,char x);
string的成员函数及其功能如下:
容器名.empty():判断当前字符串是否为空串。
容器名.size():返回当前字符串的实际字符个数(返回结果为size_type类型)。
容器名.length():返回当前字符串的实际字符个数(一般用size)。
容器名[idx]:返回当前字符串位于idx位置的字符,idx从0开始。
容器名.at(idx):返回当前字符串位于idx位置的字符。
容器名.compare(const string& str):返回当前字符串与字符串str的比较结果。在比较时,若两者相等,返回0;前者小于后者,返回-1;否则返回1。
(可以直接使用重载后的><:s1>s2,s1<s2)
容器名.append(cstr):在当前字符串的末尾添加一个字符串str。
(可以直接使用重载后的+:s1+s2)
容器名.insert(size_type idx,const string& str) :在当前字符串的idx处插入一个字符串str。
容器名.find(string& s,size_type pos):从当前字符串s中的pos位置开始查找字符串s的第一个位置,找到后返回其位置。
(需要注意的是在很多编译器中如果查找失败返回的不是-1

本文详细介绍了C++中的STL(标准模板库),包括STL的三大核心组成部分:容器(如vector、string、deque等)、算法(如find、sort等)和迭代器。STL容器提供了各种数据结构,而算法则能对容器中的数据进行操作。迭代器作为桥梁连接算法和容器,提供类似指针的功能。此外,文中还探讨了STL在算法设计中的应用,如数据存储和临时数据处理。
最低0.47元/天 解锁文章
785

被折叠的 条评论
为什么被折叠?



