STL
STL概述
c++标准模板库(Standard Template Libarary)
- STL是C++标准程序库的核心,深刻影响了标准程序库的整体结构
- STL是泛型(generic)程序库,利用先进、高效的算法来管理数据
- STL由一些可适应不同需求的集合类(collection class),以及在这些数据集合上操作的算法( algorithm)构成
- STL内的所有组件都由模板(template)构成,其元素可以是任意类型
- STL是所有C++编译器和所有操作系统平台都支持的一种库
STL六大部件
- 容器
- 分配器
- 算法
- 迭代器
- 适配器
- 仿函数
STL容器
分类
循序式容器 (sequence container)
排列次序取决于插入时机和位置
array(c++11)、vector、stack、queue、deque、priority_queue、list
关联式容器 (associative container)
排列次序取决于特定准则
set/multimap、map/multimap
STL容器的共通操作
初始化 (initialization)
容器<类型>对象名(参数)
- 产生一个空容器
list<int>a ;
vector<float>a;
deque<int>a;
stack<T>a;
- 以另一个容器元素为初值完成初始化
list<int>a;
...
vector<float>c(a.begin(),a.end());
- 以数组元素为初值完成初始化
int array[]={2,4,6,8};
...
set<int>c(array,array+sizeof(array)/sizeof(array[0]));
元素存取
操作 | 效果 |
---|---|
at(idx) | 返回索引idx所标识的元素的引用,进行越界检查 |
operater[] (idx) | 返回索引idx所标识的元素的引用,不进行越界检查 |
front() | 返回第一个元素的引用,不检查元素是否存在 |
back() | 返回最后一个元素的引用,不检查元素是否存在 |
赋值操作
操作 | 效果 |
---|---|
c1=c2 | 将c2的全部元素赋值给c1 |
c.assign(n,e) | 将元素e的n个拷贝赋值给c |
c.assign(beg,end) | 将区间[begin;end]的元素赋值给c |
c1.swap(c2) | 将c1和c2元素值互换 |
swap(c1,c2) | 同上,全局函数 |
迭代器相关函数
操作 | 效果 |
---|---|
begin() | 返回一个迭代器,指向第一个元素 |
end() | 返回一个迭代器,指向最后一个元素之后 |
rbegin() | 返回一个逆向迭代器,指向逆向遍历的第一个元素 |
rend() | 返回一个逆向迭代器,指向逆向遍历的最后一个元素 |
迭代器持续有效,除非:
- 删除或插入元素
- 容量变化而引起内存重新分配
插入(insert)函数
操作 | 效果 |
---|---|
c.insert(pos,e) | 在pos位置插入元素e的副本,并返回新元素位置 |
c.insert(pos,n,e) | 在pos位置插入n个元素e的副本 |
c.insert(pos,beg,end) | 在pos位置插入区间[beg;end]内所有元素的副本 |
c.push_back(e) | 在尾部添加一个元素e的副本 |
移除( remove)元素操作
操作 | 效果 |
---|---|
c.pop_back() | 移除最后一个元素但不返回最后一个元素 |
c.erase(pos) | 删除pos位置的元素,返回下一个元素的位置 |
c.erase(beg,end) | 删除区间[beg;end]内所有元素,返回下一个元素的位置 |
c.clear() | 移除所有元素,清空容器 |
c.resize(num) | 将元素数量改为num(增加的元素用defalut构造函数产生,多余的元素被删除) |
c.resize(num,e) | 将元素数量改为num(增加的元素是e的副本) |
容器
Vector
动态数组,运行时根据需要改变数组大小。
- 以数组形式存储,内存空间是连续的,索引可以在常数时间内完成;
- 但是在中间进行插入和删除操作,会造成内存块的拷贝
Stack 栈
特点:先进后出(FILO)
#include<stack> //头文件
Queue 队列
特点:先进先出 (FIFO)
#include<queue>//头文件
Pritrity_queue 优先队列
以某种排序准则(默认为less)管理队列中的元素
#include<queue>//头文件
- 优先队列:优先级最高的最先出列
- 队列和排序的完美结合,不仅可以存储数据,还可以价格这些数据按照设动的规则进行排序
- 每次的push和pop操作,优先队列都会动态调整,把优先级最高的元素放在前面
priority_queue<int,vector<int>,less<int> > q;//降序排列(默认)
priority_queue<int,vector<int>,greater<int> >g;//升序排列
priority_queue<double> i;//默认降序排列
q.top();//返回具有最高优先级的元素值,但不删除元素
q.pop();//删除最高优先级的元素
q.push(item);//插入新元素
struct Node{//结构体
int x,y;
//重载 "<"小于符号
bool operator < (const Node &a) const{
if(x!=a.x) return x<a.x;//按照x升序排列
else return y>a.y;//x相等时,按照y降序排序
}
};
priority_queue<Node> q;//调用
List 双向链表
内存空间不一定连续,通过指针来进行数据的访问,高效率的在任意地方进行插入和删除,插入、删除操作是常数时间;
list的元素可以是任意类型T,但是必须具备赋值和拷贝的能力;
#include <list>//头文件
list不支持随机存取,因此不提供下标操作符;
list和vector优缺点:
- vector:插入和删除操作少,随机访问元素频繁
- list:插入和删除操作频繁,随机访问少
构造、拷贝和析构
操作 | 效果 |
---|---|
listc | 产生空的list |
listc1(c2) | 产生同类型的c1,并复制c2的所有元素 |
listc(n) | 利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的list |
listc(n,e) | 产生一个大小为n的list,每个元素都是e |
listc(beg,end) | 产生一个list,以区间[beg;end]为元素初值 |
~list() | 销毁所有元素并释放内存 |
非变动性操作
操作 | 效果 |
---|---|
c.size() | 返回元素个数 |
c.empty() | 判断容器是否为空 |
c.max_size() | 返回元素最大可能数量 |
…… | …… |
特殊变动性操作
操作 | 效果 |
---|---|
c.unque | 移除重复元素,只留下一个 |
c.unque(op) | 移除使op()结果为true的重复元素 |
c1.splice(pos,c2,c2pos) | 将c2内c2pos所指元素转移到c1内的pos之前 |
c1.splice(pos,c2,c2beg,c2end) | 将c2内[c2beg;c2end)区间内所有元素转移到c1的pos之前 |
迭代器(Iterator)
容器<类型> ::iterator
- 可遍历STL容器内全部或部分元素的对象
- 指出容器中的一个特定位置
- 迭代器的基本操作
操作 | 效果 |
---|---|
* | 返回当前位置上的元素值。如果该元素有成员,可以通过迭代器以operator->取用 |
++ | 将迭代器前进至下一元素 |
==和!= | 判断两个迭代器是否指向同一位置 |
= | 为迭代器赋值 |
- 所有容器都提供两种迭代器
- container::iterator 以“读/写”模式遍历元素
- container::const_iterator 以“只读”模式遍历元素
迭代器分类
- 双向迭代器
- 可以双向行进,以递增运算前进或以递减运算后退,可以用 == 和 != 比较。
- 随机存取迭代器
- 除了具备双向迭代器的所有属性外,还具备随机访问能力;
- 可以对迭代器增加或减少一个偏移量,处理迭代器之间的距离或者使用 < 和 > 之类的关系运算符比较两个迭代器;
- vector、deque和string 提供随机存取迭代器
- stack、queue、priority_queueq不支持迭代器
Set 集合
STL中的set用二叉搜索树实现,集合中的每个元素只出现一次,且是排好序的;
访问元素的时间复杂度是O(logn)的;
例子 | 说明 |
---|---|
set A; | 定义 |
A.insert(item); | 把item放进set |
A.erase(item); | 删除元素item |
A.clear(); | 清空set |
A.empty(); | 判断是否为空 |
A.size(); | 返回元素个数 |
A.find(k); | 返回一个迭代器,指向键值k |
A.lower_bound(k); | 返回一个迭代器,指向键值不小于k的第一个元素 |
A.upper_bound(k); | 返回一个迭代器,指向键值大于k的第一个元素 |
Multiset 多重集合
与set最大区别:multiset可以插入重复的元素
如果删除,则相同的元素同时被删除
如果查找,返回该元素的迭代器的位置,如果相同则返回第一个元素的地址
其他使用与set基本类似
Map/Multimap
使用平衡二叉树管理元素
元素包含两部分(key,value),key 和 value 可以是任意类型
#include <map>//头文件
根据元素的key自动对元素排序
不能直接改变元素的key,可以通过operator[]直接存取元素值
map中不允许key相同的元素,multimap允许key相同并的元素
赋值方法
map<int,string> mapStudent;//定义
//1) insert函数插入pair数据
mapStudent.insert(pair<int,string>(1,"student_one"));
//2) 数组方式插入数据
mapStudent[2]="student_two";
map<int,string>::iterator iter; //定义迭代器
//循环输出
for(iter=mapStudent.begin();iter!=mapStudent.end();iter++){
cout<<iter->first<<" "<<iter->second<<endl;
}
iter.find(1);//查找元素
mapStudent.erase(iter);//迭代器删除
int n = mapStudent.erase(1);//关键字删除,删除成功返回1,否则返回0
mapStudent.erase(mapStudent.begin(),mapStudent.end());//成片删除