STL 贺习笔记
链接www.cnblogs.com/zhouzhendong/p/STL.html
C++ STL 的一些基础用法
本文摘抄并整理自cppreference
前言
创建一个空的 vector ,我一直是这样写的:
vector <int> v;
v.clear();
直到后来:
vector <int> v;
在 vector 里创建一个 \(0\cdots n-1\) 的数列,我一直是这样写的:
vector <int> v(0);
for (int i=0;i<n;i++)
v.push_back(i);
直到后来:
vector <int> v(n);
iota(v.begin(),v.end(),0);
我发现我根本不会用 STL,于是我决定去学一学,于是就有了这篇文章。
本文介绍一些常用的 STL 。
设 a,b 为两个迭代器,接下来默认 [a,b) 表示位于 a~b-1 的迭代器。
接下来所有变量名中,it,it1,it2,...
一般代表迭代器,x,v,...
一般代表类型为 int 的值。
1. vector
于是我们从最常用的 vector 开始。
vector 的实现基于动态数组,结合倍增思想(空间开不下了就全部删掉再开 2 倍)。
单次操作复杂度基本都是均摊 \(O(1)\) 的。
1.1 初始化
vector <int> a;//新建一个空的vector
vector <int> b(5,3);//新建一个包含 5 个 3 的 vector
vector <int> c(5);// = vector <int> c(5,0);
vector <int> d(b.begin()+1,b.end()-1);// 用 [b.begin()+1,b.end()-1) 这一段构成的数组生成 vector
vector <int> e(d);// 生成一个和 d 相同的 vector e
1.2 back
设 v 为一个 vector
则 v.back()
返回 v 的最后一个元素的引用。
例如
vector <int> v;
v.push_back(3);
cout<<v.back()<<endl;
v.push_back(5);
cout<<v.back()<<endl;
的输出结果是
3
5
1.3 begin
设 v 为一个 vector
则 v.begin()
返回一个迭代器,指向 v 第一个元素。
1.4 clear
v.clear()
表示将 v 清空(内存不释放)。
1.5 end
设 v 为一个 vector
则 v.end()
返回一个迭代器,指向 v 最后一个元素的后一个位置。
1.6 empty
设 v 为一个 vector
则 v.empty()
返回一个布尔值,表示 v 是否为空。
1.7 erase
vector <int> v(10);
iota(v.begin(),v.end(),1);
v.erase(v.begin()+5);//删除 v.begin()+5 这个位置的元素
v.erase(v.begin(),v.begin()+3);//删除 [v.begin(),v.end()) 这个区间之间的所有元素
for (auto i : v)
cout<<i<<" ";
输出结果为
4 5 6 8 9 10
1.8 front
设 v 为一个 vector
,则 v.front()
返回 v 的第一个元素的引用。
1.9 insert
vector <int> v(3,1);
vector <int> :: iterator it=v.begin();
it=v.insert(it,2);//在 it 处插入一个 2
v.insert(it,2,3);//在 it 处插入 2 个 3 ,注意这个语句执行完之后 it 就失效了
vector <int> u(3,1);
u.insert(u.begin(),v.begin(),v.end());//在 u.begin() 处插入 [v.begin(),v.end()) 这个范围内的元素
1.10 operator []
这个不用说了吧都懂。
1.11 pop_back
设 v 为一个 vector
,则 v.pop_back()
表示弹出 v 的最后一个元素。
1.12 push_back
设 v 为一个 vector
,则 v.push_back(x)
表示在 v 的最后插入一个元素 x 。
1.13 size
设 v 为一个 vector
,则 v.size()
返回当前 v 中的元素个数。
1.14 resize
1.15 relational operators
判断两个 vector 是否相等的时候,先比较 size(),然后再逐位比较。
设 a,b 为两个 vector,判断 a<b 是否成立时,按照字典序判定,也就是从 (a[0],b[0]),(a[1],b[1]),... 开始不断比较。
其他的四种比较符直接用以上两种来生成。
2. set
从这里开始,和 vector 有相同意义的函数的解释就省略了。
接下来默认定义 set <int> S
。
单次操作的复杂度基本都是 \(O(\log Size)\) 的。
它的初始化类似于 vector 。
2.1 begin
2.2 clear
2.3 count
S.count(x)
表示求 S 中 x 元素的出现次数。由于 set 中各个元素互不相同,所以只会返回 0 或 1 。
单次时间复杂度 \(O(\log Size)\) 。
1000000 次 count 的用时大约在 0.3 秒到 1 秒左右,取决于电脑的运行效率。
2.4 empty
2.5 end
2.6 erase
用于删除元素。
S.erase(it);// 删除 set 迭代器 it 指向的元素。删除完之后这个迭代器就失效了。
S.erase(x);// 删除元素 x
S.erase(it1,it2);// 删除 [it1,it2) 的所有元素
S.erase(it,S.end());// 上一种用法的一个实例
2.7 find
S.find(x)
返回一个迭代器,这个迭代器指向的元素值为 x 。
2.8 insert
S.insert(x)
表示在 S 中插入元素 x ,并返回一个 pair <set <int> :: iterator,bool>
,第一个元素表示插入元素 x 之后 x 的迭代器(如果原本就有 x 就返回原来的 x 的迭代器),第二个元素表示这次插入是否有效,如果 x 原先不在 S 中,那么返回 true,否则返回 false。
S.insert(it1,it2)
表示在 S 中插入 [it1,it2)
的所有元素。
2.9 lower_bound
S.lower_bound(x)
返回 S 中指向 大于等于 x 的最小元素 的迭代器。
2.10 upper_bound
S.upper_bound(x)
返回 S 中指向 大于 x 的最小元素 的迭代器。
2.11 size
2.12 multiset
multiset 是可重集,也就是说容器内可以有多个相同元素。
大部分用法和 set 一样,这里只讲较为不同的。
接下来默认定义 multiset <int> S
。
注意 multiset 的常数比 set 大若干倍。
2.12.1 count
S.count(x)
返回 S 中元素 x 的个数。
这里单次 count 的时间复杂度大约是 \(O(\log Size + S.count(x))\) 的。
实测常数不大,设 n = 10000,则在 S 中 insert n 个 1,再 insert 2...n 各一个,再进行 n 次 S.count(1) 的用时大约在一秒左右(不开 O2),取决于电脑的运行效率。
n=10000 时,实测用时 0.6s 的电脑,在 n = 100000 时大约要 200s,在 n = 1000 时大约要 0.02s 。
2.12.2 equal_range
S.equal_range(x)
返回类型为 pair <multiset <int> :: iterator, multiset <int> :: iterator>
第一个元素和第二个元素分别表示 S 中值为 x 的第一个迭代器位置和最后一个迭代器位置的后一个位置。
2.12.3 erase
注意一下 S.erase(x)
的作用是删除 S 中所有等于 x 的元素。
所以在要删除一个 x 的时候得写成 S.erase(S.find(x))
,这样就只会删掉一个迭代器所指向的值。
2.13 relational operators
set 和 multiset 以及 vector 类似。 唯一的区别是 set 的顺序是从小到大比较,vector 是按照下标顺序比较。
3. map
map 常用于离散化,可以当做一个下标可以是任意类型、任意值的数组用。
单次操作的时间复杂度基本都是 \(O(\log Size)\) 。
map 类型的迭代器比较特殊,例如 map <long long,int> :: iterator
指向的就是一个 pair <long long,int>
,表示元素 first 所对应的值为 second。
map 的初始化也类似于 vector 。
接下来默认定义了 map <int,int> Map
。
3.1 begin
3.2 clear
3.3 count
Map.count(x)
表示元素 x 的是否被插入过。
3.4 empty
3.5 end
3.6 equal_range
3.7 erase
和 set 中 erase 的用法是一样的。
3.8 find
和 set 中 find 的用法是一样的。
3.9 insert
map 的 insert 和 set 的 insert 略有不同。
map 中 insert 的东西是个 pair,但是 set 中是个元素。
其他都是一样的。
3.10 lower_bound
3.11 upper_bound
3.12 operator []
这个有用的重载符大概就是用 map 而不用 set 的动机吧!
Map[x]
返回 Map 中 first 是 x 的那个 pair 的 second 的引用。
例如:
map <int,int> Map;
Map[233]++;
Map[-999]+=Map[233];
Map[233]+=Map[-999];
Map[123000000]=Map[-999]+Map[233];
cout<<Map[-999]<<" "<<Map[123000000]<<" "<<Map[233]<<endl;
输出结果为
1 3 2
3.13 size
3.14 relational operators
4. unordered_map
需要 c++11 或更新的编译器才可以使用。
它是一个 Hash 表。
map 的弱化版,由于实现原理不同,所以 map 的很多功能他没有,但是它有它唯一的优势
——单次操作时间复杂度 \(O(1)\) 。
但是实测运行效率只和 map 差几倍而已。
手写 Hash 表往往能比它快 6~10 倍。
所以这里不展开介绍。
5. priority_queue
优先队列,堆。
完全可以使用 set 代替。不同于 set ,它的功能比较弱,不支持删除等一系列操作,单次操作的时间复杂度还是一样的 \(O(\log Size)\),那么它的用处是什么?
它常数小。大约是 set 的 0.5 倍。
注意优先队列 没有 迭代器。
系统默认的优先队列是大根堆。
初始化还是和 vector 差不多的。
接下来默认定义 priority_queue <int> Q
。
5.1 定义
定义一个 int 类型的大根堆:priority_queue <int> Q1
。
定义一个 char 类型的小根堆: priority_queue <char,vector <char>,greater <char> >Q2
。
重载比较运算符:
struct cmp{
bool operator () (int a,int b){
//......
}
};
priority_queue <int,vector <int>,cmp> Q3;
5.2 empty
5.3 pop
Q.pop()
表示弹出堆顶元素。
5.4 push
Q.push(x)
表示将元素 x 加入 Q 。
5.5 size
5.6 top
Q.top()
会返回 Q 的第一个元素。
6. stack
它连 operator [] 都没有,不如手写。
7. queue
它连 operator [] 都没有,不如手写。
8. deque
它叫做双端队列。
在常数要求不严格的情况下,deque 会非常好用。
deque 就像一个升级版 vector ,它在支持从后面插入的同时支持从前端插入。而且它还重载了 operator [] 。
它的初始化是和 vector 差不多的。
它的单次操作复杂度也基本都是 \(O(1)\) 。
它 有 迭代器。
下面默认定义 deque <int> Q
。
8.1 begin
8.2 clear
8.3 empty
8.4 end
8.5 erase
8.6 front
Q.front()
会返回 Q 的第一个元素的引用。
8.7 insert
8.8 operator []
Q[x]
返回 Q 从前往后数的第 x+1 个元素的引用。
8.9 pop_back
8.10 pop_front
Q.pop_front()
表示弹出 Q 的第一个元素。
8.11 push_back
8.12 push_front
Q.push_front(x)
表示在 Q 的最前面插入元素 x 。
8.13 resize
8.14 size
8.15 relational operators
STL 贺习笔记的更多相关文章
- NET Core-学习笔记(三)
这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...
- NET Core-学习笔记(二)
这里要分享的是接着上篇:NET Core-学习笔记(一)展开的继续学习core笔记,有不妥之处或者更好见解的地方希望各位朋友多多分享. 下面是本篇将要分享的学习步奏,对于刚学或者即将要学习的朋友做个相 ...
- Sass-学习笔记【进阶篇】
特别说明: 没有sass基础请移步:[Sass-学习笔记[基础篇]]http://www.cnblogs.com/padding1015/articles/7056323.html 最底部附结构图(实 ...
- Sass-学习笔记【基础篇】
最下边附结构图 在线编辑器网址如下:http://sassmeister.com/ 注意编写的时候,符号千万别用了中文的:.:.....之类的,会报错,Sass也转换不成css. less和sass ...
- PHP-学习笔记-进阶
PHP-学习笔记-进阶 PHP类和对象之定义类的方法 访问控制的关键字代表的意义为: public:公开的 protected:受保护的 private:私有的 我们可以这样定义方法: class C ...
- opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测
opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测 这章讲了 sobel算子 scharr算子 Laplacion拉普拉斯算子 图像深度问题 Canny检测 图像梯度 sobel算子 ...
- opencv-学习笔记(5)形态学转变
opencv-学习笔记(4)形态学转变 本章讲了几种形态学操作 腐蚀erode 膨胀dilate 开运算MORPH_OPEN 闭运算MORPH_CLOSE 形态学梯度MORPH_GRADIENT 礼帽 ...
- opencv-学习笔记(4)-模糊
opencv-学习笔记(4)-模糊 本章要点: 4种模糊方式 2d卷积 Cv2.filter2D(‘图像对象’,‘目标图像这里直接设为-1即可’,kernal,anchor(-1,-1)) 一般后一个 ...
- opencv-学习笔记(3)
opencv-学习笔记(3) 这章讲了 图像加法 opencv测试效率 IPYTHON测试效率 图像加法 cv2.add() 要求,两图片必须大小类型相同 然后是图像混合cv2.addWeighted ...
随机推荐
- 深入了解SQL的四种连接&不然要命的!
1.内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符).包括相等联接和自然联接. 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 stude ...
- MySql分页查询慢|这里告诉你答案
一.背景 我们在开发的过程中使用分页是不可避免的,通常情况下我们的做法是使用limit加偏移量:select * from table where column=xxx order by xxx li ...
- [Luogu P1354]房间最短路问题
这是一道紫题,然而实际上我觉得也就蓝题难度甚至不到. and,这道题就是一道数学题,代码模拟计算过程. 求最短路嘛,肯定要考虑建图,只需要把中间的墙上每个口的边缘处的点作为图中的点就行.至于为什么,显 ...
- Axure PR的使用
1759139 王越 Axure RP是美国Axure Software Solution公司旗舰产品,是一个专业的快速原型设计工具,让负责定义需求和规格.设计功能和界面的专家能够快速创建应用软件或W ...
- [C++] const与指针的关系
首先快速复习一些基础. 考虑下面的声明兼定义式: int p = 10; p的基础数据类型是int. 考虑下面的声明兼定义式: const int a = 10; a的基础数据类型是int,a是一个常 ...
- JSP+MySQL验证登录的实现方式
用IDEA连接MySQL验证登录实现方式核心部分代码 用setString的方法对从数据库中的提取的信息经行比对: try { Class.forName("com.mysql.jdbc.D ...
- 机器学习用Pandas实现数据库的读取
#读取数据库数据#import pandas as pd 导入模块#import pymysql 导入数据库模块#con = pymysql.connect(host='localhost',po ...
- 2018-2019-2 20165234 《网络对抗技术》 Exp4 恶意代码分析
实验四 恶意代码分析 实验目的 1.监控自己系统的运行状态,看有没有可疑的程序在运行. 2.分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals ...
- ubuntu server 16.04 安装过程中提示无法安装busybox-initramfs
这个问题在安装desktop版本时是不会出现的,只有server才有这个问题. 出现这个问题与硬件平台无关,不管是虚拟机还是物理机都会出现,解决的办法是在安装开始界面选择English,后面Langu ...
- 21 re正则模块 垃圾回收机制
垃圾回收机制 不能被程序访问到的数据,就称之为垃圾 引用计数 引用计数:用来记录值的内存地址被记录的次数的:当一个值的引用计数为0时,该值就会被系统的垃圾回收机制回收 每一次对值地址的引用都可以使该值 ...