STL(Standard Template Library)
STL(StandardTemplateLibrary) 标准模板库,是“容器”的集合。
STL中常见的集合有:向量(vector)、栈(stack)、队 列 (queue)、优先队列(priority queue)、链表 (list)、集合 (set)、映射 (map)等容器。
STL容器的通用操作:
1.与大小相关的操作(size operator)
size() 返回当前容器的元素数量
empty() 判断当前容器是否尾空
max_size() 返回容器能容纳的最大元素数量
2.比较(comparison)
比较通常是这些运算符:
·比较操作两端的容器必须属于同一类型
·如果两个容器内的所有元素按序相等,那么这两个容器相等
·采用字典序判断某个容器是否小于另一个函数
3.元素操作
Insert(pos,e); 将元素e拷贝并安插于迭代器pos所指位置
erase(begin,end); 移除[begin,end]区间内的所有元素
clear(); 移除所有元素
swap 用于交换元素
4.与迭代器(iterator)相关的操作(容器需要支持迭代器)
begin() 返回一个迭代器,指向第一个元素
end() 返回一个迭代器,指向最后一个元素之后
rbegin() 返回一个迭代器,指向最后一个元素
rend() 返回一个迭代器,指向第一个元素之前
5.比较器
1: less
2: greater
目录
前言: - 1 -
STL容器的通用操作: - 1 -
- 与大小相关的操作(size operator) - 1 -
- 比较(comparison) - 1 -
- 元素操作 - 1 -
- 与迭代器(iterator)相关的操作(容器需要支持迭代器) - 1 -
第一章:string - 1 -
一、string的输入以及访问 - 1 -
二、string的操作函数 - 1 -
三、string的侦测函数 - 2 -
第二章:向量vector - 3 -
一、什么是vector? - 3 -
二、 vector里常见的函数: - 3 -
(一) 定义一个向量vector - 4 -
(二)vector的插入,删除,获取头、尾指针 - 4 -
(三)对vector进行排序,交换,清空 - 5 -
第三章:迭代器 - 6 -
(一) 什么是迭代器? - 6 -
(二) 定义一个迭代器 - 6 -
(三) 遍历一个迭代器 - 6 -
A、正向迭代器。 - 6 -
B、 双向迭代器。 - 7 -
C、 随机访问迭代器。 - 7 -
第四章:deque双向队列 - 8 -
一 、什么是 deque - 8 - - deque的特点: - 8 -
2.deque 有两种 vector 没有的成员函数: - 8 -
3、deque 使用注意: - 8 -
第五章:list-链表 - 9 -
一、 什么是list(链表) - 9 - - 什么是list(链表) - 9 -
- 它的特点是什么 - 9 -
二. list里常见的函数 - 9 -
三、list的应用 - 10 -
(一) 定义一个list - 10 -
(二) list的插入,删除,获取头、尾迭代器 - 10 -
第五章:集合-set - 11 -
一、 什么是set - 11 -
二、 set的一些常见的用法: - 11 -
第六章:stack-栈 - 13 -
一、 什么是栈 - 13 -
二、 栈的常见函数: - 13 -
第七章:queue-队列 - 15 -
一、什么是queue队列 - 15 -
二、queue里常见的函数: - 15 -
第八章:priority queue-优先队列 - 1 -
一、 什么是优先队列 - 1 -
第一章:string
一、string的输入以及访问
- getline(cin,s);
读入一个字符串(直到换行),可以含空格;
2.cin>>;
读入一个字符串,不能含空格;
3.a[];
获取字符串a的某一个下标对应的字符;
4.s.begin();
获取字符串s的头指针
5.s.end();
获取字符串s的尾指针
二、string的操作函数
- substr(x,len);
从下标x,截取长度为len的字符串;
2.substr(x);
从下标x,截取到最后;
3.erase(x,len);
删除字符串第x个下标开始的len个字符;
4.erase(x);
删除字符串第x个下标开始往后的所有字符;
5.insert(x,s);
在字符串下标为x的位置插入一个字符串s;
6.replace(x,len,str);
从下标为x开始,替换len个字符为str;
7.s.erase(x,y);
删除字符串s中x的后y位;
三、string的侦测函数
- s.find("侦测字符");
找出s里这个字符出现的位置;
2.a.find(x)
查找字符串a中字符串x第一次出现的下标i,没有返回string::npos(-1);
3.a.find(str,x);
在字符串a的下标x之后,查找str第一次出现的下标;
第二章:向量vector
一、什么是vector?
向量 (vector) 是一个顺序容器 (Sequence Container),它能够存放各种类型的对象。
可以简单的认为, 向量是一个能够存放任意类型的动态数组(元素个数可变)。
二、vector里常见的函数:
函数名 函数说明
push back(元素) 增加一个元素到向量后面
insert(位置,元素) 插入元素到向量的指定位置
insert(位置,个数n,元素) 插入n个相同的元素到指定位置
insert(位置,向量头指针 first,向量尾指针end) 将另一个向量从first位置开始到end结束(不包括end)之间的内容 插入该向量的指定位置。
erase(位置) 删除指定位置的元素
erase(开始位置,结束位
置 ) 删除向量中(first,last)中元素
pop back() 弹出(删除)向量的最后一个元素
clear() 清除向量所有元素,size()变为0
运算符[i] 取向量下标为i的元素
front() 取向量第一个元素
back() 取向量最后一个元素
begin() 返回向量头指针(迭代器),指向第一个元素
end() 返回向量尾指针,指向向量最后一个元素的下一个位置
rbegin() 反向迭代器,指向最后一个元素
rend() 反向迭代器,指向第一个元素之前的位置
size() 返回向量中实际元素的个数。
resize(大小) 重新设定向量的大小,也就是可以保存元素的个数。
max size() 得到vector最大可以是多大。
empty() 判断向量是否为空,等价于size()为0。
swap() 交换两个同类型向量的数据。
对应于数组,要注意:向量的大小是可变的,开始时向量为空,随着不断插入元素,向 量自动申请空间,容量变大。
注意学会使用: sort()、reverse()等函数对vector进行排序、逆序等操作
例子:
(一)定义一个向量vector
例子:想要定义一个变量类型为(int)且长度为5的vector的向量,并将其默认值设为0,应该如下操作
vector
vector<变量类型>向量名;
向量名.push_back(数据);
向量名.push_back(数据);
…
方法一:例如:想要在vector v中存储{9,5,4},应该如下操作
vector
v.push_back(9);
v.push_back(5);
v.push_back(4);
方法二:例如:想要在定义一个长度为5的vector v,且默认值为x,应该如下操作:
vector
方法三:例如:想要把一个区间复制到一个vector v,应该如下操作:
vector(数组头指针,数组尾指针);
(二)vector的插入,删除,获取头、尾指针
1.vector的插入
方法一:例如:想要向vector v中下标为i的位置插入一个元素x,应该如下操作:
v.insert(i,x);
方法二:例如:想要向vector v中下标为i的位置插入一个x个元素y,应该如下操作:
v.insert(i,x,y);
方法三:例如:想要向vector v中下标为i的位置插入vector a的一部分,应该如下操作:
v.insert(i,a.头指针,a.尾指针);
2.vector的删除
方法一:例如:想要删除vector v中下标为i的元素,应该如下操作:
v.erase(i);
方法二:例如:想要删除vector v中下标为i的元素删除到最后,应该如下操作:
v.erase();
3.获取vector的头尾元素
获取头元素
例子:想要获取vector v的第一个元素,应该如下操作:
v.front();
获取尾元素
例子:想要获取vector v的最后一个函数,应该如下操作:
v.back();
- 获取vector的头尾指针
获取头指针
例子:想要获取vector v的头指针,应该如下操作:
v.begin();
获取尾指针
例子:想要获取vector v的尾指针,应该如下操作:
v.end();
(三)对vector进行排序,交换,清空
升序排序:
例子:想要将vector v进行升序排序的话,应该如下操作:
sort(v.begin,v.end());
降序排序:
例子:想要将vector v进行降序排序的话,应该如下操作:
reverse(v.begin(),v.end());
交换位置:
例子:想要将vector v1和vector v2交换位置,应该如下操作:
swap(v1,v2);
清空向量:
例子:想要把vector v向量给全部清空,应该如下操作:
clear(v);
第三章:迭代器
(一)什么是迭代器?
迭代器 (iterator): 用来指向、遍历、修改容器元素的变量,类似指针。它还可以遍历STL 容器内全部或部分元素的对象,且指出容器中的一个特定位置。
常用的迭代器按功能强弱分为: 输入、输出、正向、双向、随机访问五种。
不同容器的迭代器,其功能强弱有所不同。例如,排序算法需要通过随机访问迭代器来访问 容器中的元素,因此有的容器就不支持排序算法。
(二)定义一个迭代器
正向迭代器通常这样定义: 类型::iterator 迭代器名;
反向迭代器通常这样定义: 类型::reverse_iterator 迭代器名;
不同类型迭代器的定义:
容器 迭代器类别
vector 随机
deque 随机
list 双向
set/multiset 双向
map/multimap 双向
stack 不支持迭代器
queue 不支持迭代器
priority queue 不支持迭代器
(三)遍历一个迭代器
操作 效果
- 返回当前位置上的元素值。如果该元素有成员,可以通过迭代器以operator-> 取用
++ 将迭代器前进至下一元素
== != 判断两个迭代器是否指向同一位置
= 为迭代器赋值(将所指元素的位置赋值过去)
常用的迭代器按功能强弱分为: 输入、输出、正向、双向、随机访问五种,这里只介绍常用 的三种。
A、正向迭代器。
·假 设 p 是一个正向迭代器,则 p 支持以下操作:++p,p++,*p。
·此外,两个正向迭代器可以互相赋值,还可以用=和!=运算符进行比较。
B、 双向迭代器。
·双向迭代器具有正向迭代器的全部功能。
·双向迭代器p 支持-p 和 p--, 使得 p 朝和++p 相反的方向移动。
C、 随机访问迭代器。
√ 随机访问迭代器具有双向迭代器的全部功能。
√ 随机访问迭代器p 还支持以下操作:
p+=i: 使得 p 往后移动 i 个元素。
p-=i: 使得 p 往前移动 i 个元素。
p+i: 返 回 p 后面第 i 个元素的迭代器。
p-i: 返 回 p 前面第 i 个元素的迭代器。
p[i]: 返回 p 后面第 i 个元素的引用。
两个随机访问迭代器 p1、p2 还可以用<、>、<=、>=运算符进行比较。 pl<p2 的含义是:p1 经过若干次(至少一次)++操作后,就会等于p2。
表达式p2-p1 表示迭代器 p2 所指向元素和迭代器 p1 所指向元素的序号差 (p2和pl 之间的元素个数减一)。
第四章:deque双向队列
一 、什么是 deque
deque 也是顺序容器的一种,也是一个可变长数组。要使用 deque, 需要包含头文集deque(“<bits/stdc++.h>”除外)。
所有适用于vector的操作都适用于deque,deque在头尾增删元素性能较好。
1.deque的特点:
·deque和vector有很多类似的地方。在deque中,随机存取任何元素都能在常数时间内完成(但慢于vector)。
·它相比于vector的优点是,vector在头部删除或添加元素的速度很慢,在尾部添加元素的性能较好,而deque在头尾增删元素都具有较好的性能(大多数情况下都能在常数时间内完成)。
2.deque 有两种 vector 没有的成员函数:
·void push front(const T& val);//将 val 插入容器的头部
·void pop front(); // 删除容器头部的元素
3、deque 使用注意:
·deque 支持随机存取
·deque 支持在头部和尾部存储数据
·deque 不支持 capacity 和 reserve 操作
第五章:list-链表
一、什么是list(链表)
1.什么是list(链表)
list:是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息
块(即实际存储的数据)、 一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可 以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。 是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即 实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意
伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。
2.它的特点是什么
·list随机检索的性能非常的不好,因为它不像vector那样直接找到元素的地址,而是
要从头一个一个的顺序查找。
· 但是它可以迅速地在任何节点进行插入和删除操作,因为list的每个节点保存着它在
链表中的位置,插入或删除一个元素仅对最多三个元素有所影响。
·list支持双向迭代器,没有下标,必须使用迭代器遍历list。(由于不支持随机迭代器,
不能写迭代器+x,迭代器-x,不能用sort()函数,但list拥有sort成员函数 )
二.list里常见的函数
函数名 函数说明
push back(元素) 往链表尾部添加元素
push front(元素) 往链表头部添加元素
pop back(元素) 链表尾部移除元素
pop front(元素 链表头部移除元素
insert() 在指定位置插入一个或多个元素
begin() 获取链表的起始地址
end() 获取链表的结束地址
size() 返回链表元素个数
max size() 获取链表支持的最大容量
erase(开始地址,结束地址) 删除链表中指定范围之间的元素
remove(值val) 删除和val相等的元素
clear() 清空链表
empty() 判断链表是否为空
reverse(开始地址,结束地址) 翻转链表所有值
sort(链表对象) 链表元素排序
三、list的应用
(一)定义一个list
例子:想要定义一个变量类型为(int)且长度为5的list的向量,并将其默认值设为0,应该如下操作
list
方法一:例如:想要在list v中存储{9,5,4},应该如下操作
list
l.push_back(9);
l.push_back(5);
l.push_back(4);
方法二:例如:想要在定义一个长度为5的list l,且默认值为x,应该如下操作:
list
方法三:例如:想要把一个区间复制到一个list l,应该如下操作:
list
(二)list的插入,删除,获取头、尾迭代器
1.插入
方法一:例如:想要向list l中下标为i的位置插入一个元素x,应该如下操作:
l.insert(i,x);
方法二:例如:想要向list l中下标为i的位置插入一个x个元素y,应该如下操作:
l.insert(i,x,y);
方法三:例如:想要向list l中下标为i的位置插入list a的一部分,应该如下操作:
l.insert(i,a.头指针,a.尾指针);
第五章:集合-set
一、什么是set
set是关联容器的一种,是排序好的集合(元素已经进行了排序),set中不能有重复的元素。
注意:
· 不能直接修改 set容器中元素的值。因为元素被修改后,容器并不会自动重新调整顺序,于是容器的有序性就会被破坏,再在其上进行查找等操作就会得到错误的结果。因此,
如果要修改set容器中某个元素的值,正确的做法是先删除该元素,再插入新元素。
·multiset 容器就像 set 容器,但它可以保存重复的元素。
·set支持双向迭代器(不支持随机迭代器),在插入和删除时,要特别注意。
·在STL 中使用结构体,需要对特定要求的运算符进行重载(operator);STL默认使用小于号来排序, 因此,默认重载小于号; (如果使用greater<>比较器就需重载大于号),且要注意让比 较函数对相同元素返回 false。
二、set的一些常见的用法:
函数名 函数说明
begin() 获取set容器的起始地址
end() 获取set容器的结束地址
insert() 插入set容器
erase(开始地址,结束地
址 ) 删除set容器中指定范围之间的元素,set也支持直接删除
值
find() 查找匹配的元素迭代器,若不存在,返回set.end()
clear() 清空set容器
size() 返回set容器元素个数
empty() 判断set容器是否为空
1.插入:
插入:
例子:想要增添一个60到set s:
s.insert(60);
2.删除:
例子:想要删除set s的第一个元素:
s.erase(s.begin());
例子:想要删除set s内值为30的元素:
s.erase(30);
3.查找
例子:想要在set s里查找30的元素:
s.find(30);//返回迭代器
第六章:stack-栈
一、什么是栈
1.什么是容器适配器
STL中的容器适配器有stack、queue、priority queue三种。它们都是在顺序容器的基础 上实现的,屏蔽了顺序容器的一部分功能,突出或增加了另外一些功能。
容器适配器都有以下三个成员函数:
·push(): 添加一个元素。
·top(): 返回顶部(对stack而言)或队头(对 queue、priority queue 而言)的元素的 引用。
·pop(): 删除一个元素。
容器适配器是没有迭代器的,因此 STL中的各种排序、查找、变序等算法都不适用于容器 适配器。
2.什么是栈
栈是一种后进先出 (First in last out, 简称 FILO 或者LIFO) 的元素序列,访问和删除都只能 对栈顶的元素(即最后一个被加入栈的元素)进行,并且元素也只能被添加到栈顶。栈内的 元素不能访问。如果一定要访问栈内的元素,只能将其上方的元素全部从栈中删除,使之变 成栈顶元素才可以。
stack 容器有广泛的应用。例如,编辑器中的 undo (撤销)机制就是用堆栈来记录连续的变化。 撤销操作可以取消最后一个操作,这也是发生在堆栈顶部的操作。
二、栈的常见函数:
函数名 函数说明
push(元素) 入栈
pop() 出栈
top() 返回栈顶元素
size() 返回元素个数
empty() 判断栈是否为空
定义一个空栈,应该如下操作:
stack
想要把{9,5,4}放到栈里,应该如下操作
stack
s.push(9);
s.push(5);
s.push(4);
想要弹出上边的栈的所有元素,应该如下操作:
s.pop(); 弹出时回依次弹出9,5,4
s.pop();
s.pop();
想要输出栈顶元素,应该如下操作:
cout<<s.top();
想要暑促栈内元素的个数,应该如下操作:
cout<<s.size();
第七章:queue-队列
一、什么是queue队列
queue: 就是“队列”。 队列是先进先出的(First in first out), 队头的访问和删除操作只能在队头进行,添加操作只能在队尾进行。不能访问队列中间的元素。
·queue 可以用 list 和 deque 实现,默认情况下用 deque 实现。
特点:先进先出 (FIFO), 队尾进,队头出。
二、queue里常见的函数:
函数名 函数说明
push(元素) 进队,从队尾入队
pop() 出队,从队头出队
front() 返回队头元素
back() 返回队尾元素
size() 返回队列中元素个数
empty() 判断队列是否为空
(一)定义一个队列
queue
(二)对queue的操作
入队:
例子:想要将{1,1,4,5,1,4}依次入队,应该如下操作:
q.push(1);
q.push(1);
q.push(4);
q.push(5);
q.push(1);
q.push(4);
出队:
例子:想要让队列出队,应该如下操作:
q.back();
获取队头元素:
例子:想要输出队列{1,1,4,5,1,4}的对头元素应该如下操作:
cout<<q.front;
第7.5章:priority queue-优先队列
一、什么是优先队列
priority_queue :是“优先队列”它和普通队列的区别在于优先队列的队头元素总是最大的——即执行pop操作时,删除的总是最大的元素;执行top操作时,返回的是最大元素的引用。
·priority_queue 可以用 vector 和 deque 实现,默认情况下用 vector 实现。
·priority queue 默认的元素比较器是 less
·priority_queue 的第三个类型参数可以用来指定排序规则。
·优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序。
·priority_queue内部并非完全有序,但却能确保最大元素总在队头。
定义: priority queue<Type,Container,Functional>
·Type 就是数据类型:
·Container 就是容器类型(Container 必须是用数组实现的容器,比如 vector,deque 等等,但不能用 list。STL里面默认用的是vector);
·Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数, 使用基本数据类型时, 只需要传入数据类型, 默认是大顶堆。
priority queue特别适用于"不停地在一堆元素中取走最大的元素 "这种情况 。
priority queue 插入和删除元素的复杂度都是0(log(n))。 虽然用 set/multiset 也能完 成此项工作,但是 priority queue 比它们略快一些。
二、优先队列里常见的函数
定义一个优先队列:
priority_queue<int,vector
出队:
q.pop();
获取队头元素:
例子:想要输出队列q的队头元素,应该如下操作:
cout<<q.top();