持续更新中😬 加个关注,后续上新不错过~
一、STL简介
STL最早由惠普实验室开发完成,它是以C中的模板语法为基础建立起来的一套包含基础数据结构和算法的代码库。STL的特点是实现了“类型参数化”,即STL的代码中可处理任意自定义类型的对象。
STL中提供的容器用来保存数据,涵盖了许多数据结构,如链表、栈和队列等。在实际的开发过程中可以直接使用,不仅简化了许多重复、乏味的工作,而且提高了软件开发的效率。
容器部分主要由头文件vector、 list、 deque、 set、map、 stack 和 queue 组成。下图中列出了STL提供的数据结构和相应头文件的对应关系(其中以*标识的以hash_开头的4个容器必须存在一个键值的哈希函数,它们不是C++标准库的部分)
为此,在使用STL时必须将以下语法插入到源代码文件开头:
using namespace std;
这样直接把程序代码定位到std命名空间中。
二、STL迭代器的常用运算
++:正向移动迭代器
–:反向移动迭代器
*:返回迭代器所指的元素值
三、数据结构和相应头文件的对应关系
数据结构 | 说明 | 实现头文件 |
---|---|---|
向量(vector) | 连续存储元素。底层数据结构为数组,支持快速随机访问 | vector |
链表(list) | 由结点组成的双向链表,每个节点包含着一个元素,底层数据结构为双向链表,支持快速增删 | list |
栈(stack) | 后进先出的序列。底层一般用list或deque实现,封闭头部即可,不用vector的原因是容器大小有限制,扩容耗时 | stack |
队列(queue) | 先进先出的序列。底层一般用list或deque实现,封闭头部即可,不用vector的原因同上 | queue |
双队列(deque) | 连续存储的指向不同元素的指针所组成的数组。底层数据结构为一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,也支持随机访问 | deque |
优先队列(priority_queue) | 元素的次序是由作用于所存储的值上的某种谓词决定的一种队列。底层数据结构一般为vector作为底层容器,堆heap作为处理规则来管理底层容器实现 | queue |
集合(set) | 由结点组成的红黑树,每个结点都包含着一个元素,结点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序。底层数据结构为红黑树,有序,不重复 | set |
多重集合(multiset) | 允许存在两个次序相等的元素的集合。底层数据结构为红黑树,有序,可重复 | set |
映射(map) | 由(关键字,值)对组成的集合,以某种作用于关键字上的谓词排列。底层数据结构为红黑树,有序,不重复 | map |
多重映射(multimap) | 允许关键字相等的次序的映射,底层数据结构为红黑树,有序,可重复 | map |
hash_set* | 类似于集合,底层数据结构为哈希表,无序,不重复 | <hash_set> |
hash_multiset* | 类似于多集合,底层数据结构为哈希表,无序,可重复 | <hash_set> |
hash_map* | 类似于映射,底层数据结构为哈希表,无序,可重复 | <hash_map> |
hash_multimap* | 类似于多映射,底层数据结构为哈希表,无序,可重复 | <hash_map> |
四、几种常用的容器
1. vector(向量容器)
它是一个向量类模板。向量容器相当于数组,它存储具有相同数据类型的一组元素,可以从后面快速地插入与删除元素,快速地随机访问元素,但是在序列中间插入、删除元素较慢,因为需要移动插入或删除处于后面的所有元素。而且如果一开始分配的空间不够,重新分配更大的空间时需要进行大量的元素复制,从而增加了性能开销。
以下语句定义一个整数向量对象 test:
vector rest;
这样只定义一个空的容器,其中没有任何数据,vector提供了一系列的成员函数,可以使用它们对定义的test容器进行操作。
(1)vector主要的成员函数
- max_size():容器中能保存的最大元素数量
- size():当前容器中的实际元素个数
- push_bach():在vector的尾部添加一个元素
- insert():将元素插入到指定元素之前
- empty():判断vector是否为空
- front():取得vector的第一个元素
- back():取得vector的最后一个元素
- erase():去掉某个区间指定的元素
- clear():删除所有元素
- begin():引用容器中的第一个元素
- end():引用容器中最后一个元素后面的一个位置
(2)例子
a. 代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v(3); // 定义初始长度为3的整数容器
v[0]=5; // 下标0处放置元素5
v[1]=2; // 下标1处放置元素2
v.push_back(7); // 在尾部插入元素7
vector<int>::iterator first=v.begin(); // 让first指向开头元素
vector<int>::iterator last=v.end(); // 让last指向尾部元素
while(first!=last){ // 循环输出所有元素
cout<<*first++<<" ";
}
cout<<endl;
return 1;
}
b. 运行结果
c. 分析
在上述程序中初始定义了一个长度为3的整数向量v(所有元素默认为0)。在前两个下标放置两个整数,再在末尾插入一个整数7,长度增加1,最后输出所有整数。
2. deque(双端队列容器)
它是一个双端队列类模板。双端队列容器可以从前面或后面快速地插入与删除元素,并可以快速地随机访问元素,但删除元素较慢,空间的重新分配要比vector快,重新分配空间后原有的元素不需要复制。若要对deque进行排序操作,可将deque先复制到vector,排序后再复制回deque。
(1)deque主要的成员函数
- empty():判断队列是否为空队
- size():返回队列中元素的个数
- push_front():在队头插入元素
- push_back():在队尾插入元素
- pop_front():删除队头的一个元素
- pop_back():删除队尾的一个元素
- clear():删除所有元素
- begin():引用容器中的第一个元素
- end():引用容器中最后一个元素后面的一个位置
(2)例子
a. 代码
#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;
void disp(deque<int>&dq)
{
deque<int>::iterator iter;
for(iter=dq.begin();iter!=dq.end();iter++){
cout<<*iter<<" ";
}
cout<<endl;
}
int main()
{
deque<int> dq; // 建立一个双端队列 dq
dq.push_front(1); // 队头插入1
dq.push_back(2); // 队尾插入2
dq.push_front(3); // 队头插入3
dq.push_back(4); // 队尾插入4
disp(dq); // 输出dq的所有元素
dq.pop_front(); // 删除队头元素
dq.pop_back(); //删除队尾元素
disp(dq);
return 1;
}
b. 运行结果
c. 分析
在上述程序中定义了字符串双端队列dq,利用插入和删除成员函数进行操作。
3. list(链表容器)
它是一个双链表类模板,可以从任何地方快速地插入与删除。它的每个元素间用指针相连,不能随机访问元素,为了访问表容器中特定的元素,必须从第1个位置(表头)开始,随着指针从一个元素到下一个元素,直到找到要找的元素。插入元素比vector快,对每个元素分别分配空间,所以不存在空间不够重新分配的情况。
(1)list主要的成员函数
- size():返回表中实际元素的个数
- empty():判断链表是否为空
- push_back():在表尾部插入元素
- pop_back():删除最后一个元素
- remove():删除所有指定值的元素
- erase():从容器中删除一个或几个元素
- clear():删除所有的元素
- insert(pos,elem):在pos处插入elem元素并返回该元素的位置
- begin():引用容器中的第一个元素
- end():引用容器中最后一个元素后面的一个位置
(2)例子
a. 代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int>lst;
list<int>::iterator i,start,end;
lst.push_back(5);
lst.push_back(2);
lst.push_back(4);
lst.push_back(1);
lst.push_back(3);
lst.push_back(8);
lst.push_back(6);
lst.push_back(7);
cout<<"lst:";
for(i=lst.begin();i!=lst.end();i++){
cout<<*i<<" ";
}
cout<<endl;
i=lst.begin();
start=++lst.begin();
end=--lst.end();
lst.insert(i,start,end);
cout<<"lst.insert(i,start,end)"<<endl;
cout<<"lst:";
for(i=lst.begin();i!=lst.end();i++){
cout<<*i<<" ";
}
cout<<endl;
return 1;
}
b. 运行结果
c. 分析
建立了一个整数表对象lst,向其中添加8个元素,i指向元素5,start指向元素2,end指向元素6,执行“lst。Insert(i,start,end);”语句时将2,4,1,3,8,6插入到最前端
4. stack(栈容器)
它是一个栈类模板。栈具有后进先出的特点。栈容器必须结合其他容器使用,其默认的内容是deque。它先进后出,只有一个出口,不允许遍历。
(1)stack主要的成员函数
- empty():容器中没有元素时返回true,否则返回false
- size():返回容器中当前元素个数
- top():返回栈顶元素
- push():元素进栈
- pop():元素出栈
(2)例子
a. 代码
#include <iostream>
#include <stack>
using namespace std;
int main()
{
stack<int>st;
st.push(1);
st.push(2);
st.push(3);
st.pop();
cout<<st.top()<<" ";
st.pop();
st.top()=7;
st.push(4);
st.push(5);
st.pop();
while(!st.empty()){
cout<<st.top()<<" ";
st.pop();
}
cout<<endl;
return 1;
}
b. 运行结果
c. 分析
建立了一个整数栈对象st,进栈、退栈若干元素,最后使用while循环语句在栈不空时输出栈顶元素并退栈。
5. queue(队列容器)
它是一个队列类模板。队列具有先进先出的特点,队列容器是受限制的deque,内部容器一般使用list较简单。它先进先出,不允许遍历。
(1)queue主要的成员函数
- empty():容器中没有元素时返回true,否则返回false
- size():返回容器中当前元素的个数
- front():返回队头元素
- back():返回队尾元素
- push():元素进栈
- pop():元素出栈
(2)例子
a. 代码
#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue<int>q;
q.push(1);
q.push(2);
q.push(3);
cout<<q.front()<<" ";
q.pop();
cout<<q.front()<<" ";
q.pop();
q.push(4);
q.push(5);
q.pop();
while(!q.empty()){
cout<<q.front()<<" ";
q.pop();
}
cout<<endl;
return 1;
}
b. 运行结果
c. 分析
建立了一个整数队对象q,进队、出队等若干元素,最后使用while循环语句在队不空时输出对头元素并出队。
若有帮助的话,请点个赞吧!😊