导学_常见STL讲解

第九册第01课时    常见STL讲解

一、常见STL讲解

标准模板库

C++的标准模板库中封装了很多常用的容器,包含了诸多常用的数据结构与基本算法。算法竞赛常用的STL:算法函数(alogorithm)、栈(stack)、队列(queue)、优先队列(priority_queue)、双端队列(deque)、向量(vector)、集合(set)、多重集合(multiset)、映射(map)、无序映射(unordered_map)、数对(pair)等。  
每种数据结构都有自己的实现细节,STL 库把一切细节都隐藏起来,使用统一的接口(命令)格式(头文件),供简单方便使用。
学习 STL 部分内容时,需要大家动手实践尝试!

stack与queue

stack(栈)是STL实现的栈容器,queue(队列)是STL实现的队列容器。栈和队列容器可以实现基本的栈与队列功能。以下所有操作时间复杂度O(1)。

stack操作:
stackst;常用函数功能
st.push(x)将x入栈
st.top()获取栈顶元素
st.pop()弹出栈顶元素
st.empty()判断栈空,空为true,否则为false
st.size()返回stack内元素个数
queue操作:
queueq;常用函数功能
q.push(x)将x入队
q.front()返回队头
q.back()返回队尾
q.pop()队首元素出队
q.empty()判断队空,空为true,否则为false
q.size()返回queue内元素个数

deque

头文件:  
deque是STL的双端队列容器,可以在队头和队尾入队或出队  
单调队列算法是通过双端队列实现的  
双端队列操作:

dequeq;常用函数功能
q.back()返回队尾元素
q.front()返回队首元素
q.push_back(x)从队尾将x入队
q.push_front(x)从队首将x入队
q.pop_back()队尾元素出队
q.pop_front()队首元素出队
q.size()返回deque内元素个数
q.empty()判断队空,空为true,否则为false

练习题A 括号匹配

题目描述

假设表达式中允许包含圆括号和方括号两种括号,其嵌套的顺序随意,如()或[([][])]等为正确的匹配,[(])或(或(()))均为错误的匹配  
本题的任务是检验一个给定的表达式中的括号是否匹配正确  
输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出“OK”,不匹配就输出“Wrong”。

输入描述

一行字符,只含有圆括号和方括号,个数小于 255。

输出描述

匹配就输出一行文本“OK“,不匹配就输出一行文本”Wrong”

输入样例
[(])
输出样例
Wrong

练习题B 周末舞会

题目描述

假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴。规定每个舞曲能有一对跳舞者。若两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。现要求写一个程序,模拟上述舞伴配对问题。(0<m,n,k<1000)

输入描述

第一行男士人数m和女士人数n;  
第二行舞曲的数目k。

输出描述

共k行,每行两个数,表示配对舞伴的序号,男士在前,女士在后。

输入样例
2 4
6
输出样例
1 1
2 2
1 3
2 4
1 1
2 2

vector

vector(向量)本质就是一个动态大小的数组,可以存放任意类型的对象。

vector<int> a(10); //定义了 10 个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的 O(n)
vector<int> a(10,1); //定义了 10 个整型元素的向量,且元素的初值都为 1 O(n)
vector<int> a(b); //用 b 向量来创建 a 向量,整体复制性赋值 O(n)
vector<int> a(b.begin(),b.begin+3); //a 的初值为向量 b 的前三个值 O(n)
int b[7]={1,2,3,4,5,9,8};vector<int> a(b,b+7); //从数组中获得初值 O(n)
v[i]; // 以下标方式访问元素 O(1)
v.push_back(x); //往尾部插入元素 x (常用) O(1)
v.insert(it, x); //向迭代器 it 指向的位置插入 x,原位置后移 O(n)
v.size();//返回表长,注意是 unsigned 类型 O(1)
v.front(); //取首元素的值 v.back(); // 取尾元素的值 O(1)
v.empty(); //表为空返回真,否则返回假  O(1)
v.clear(); //清空表 O(1)
v.pop_back(); // 删除表尾元素  O(1)
v.erase(it); //删除迭代器 it 指向的元素 O(1)

vector迭代器

要访问顺序容器和关联容器中的元素,需要通过“迭代器(iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。接下来看一个通过迭代器遍历vector容器的例子:

vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++){
    cout<<*it<<endl;
}
迭代器的定义:

容器类型::iterator 迭代器名称  
容器类型取决于迭代器指向什么容器,如vector,vector

迭代器的增减:

迭代器可以使用++或–指向下一个元素或上一个元素  
vector的迭代器也可以是+或-一个数值,如it+3代表迭代器变换为后面的第三个元素

迭代器取值:

迭代器变量it存储的并不是容器中元素的值,而是类似于指针存储一个地址类型,所以要取it所指向的元素的值,需要用运算符*

map映射

头文件  
map是STL的一个关联容器,翻译为映射,数字也是一种映射。如int a[10]是int到int的映射,而a[5]=25,是把5映射到25。  
普通int数组是map<int,int>a;  
字符到整型的映射是 map<char,int>a;  
字符串到整型的映射是 map<string,int>a。  
map容器内元素的访问——通过下标访问  
和访问普通的数组是一样的,例如对一个定义为map<char,int>mp的map来说,就可以直接使用mp[‘c’]的方式来访问它对应的整数。  
当建立映射时,就可以直接使用mp[‘c’]=20这样和普通数组一样的范式。但是要注意的是,map中的键是唯一的。

常用的map方法:

map<int,int>m;  
m.find(x):find是查找是否存在。  
m.count(x):count是查找键为x的数量。(等同于查找x是否存在)  
m.empty():判断是否为空  
m.size():容器内元素数量  
m.insert(x):x必须为对的形式。可以为pair的形式,通过make_pair创建。  
m.erase(x):将键值为x的元素删除。  
m.clear():清空map  
map的底层是红黑树,所以查找、插入、删除、访问的时间复杂度都是log级

map迭代器

迭代器定义:
map<int,int>::iterator it;
map<char,int>::iterator it;
map<string,int>::iterator it;
map迭代器特性:

map是有序的,根据第一关键字自动排序,如map内只有两个元素:  
mp[14]=5  
mp[1000]=1  
则遍历map时会先遍历到mp[14],再遍历到mp[1000]  
map的迭代器it取值不用*,而用->first取第一关键字,->second取第二关键字  
map的迭代器只能++,–,不能±数值

unordered_map

头文件<unordered_map>  
unordered_map是和map类似的STL容器,用来完成映射的操作。  
不同的是,unordered_map底层实现是哈希表,不是自有序的,是无序的,增删改查的速度也比map要快一些。

定义方法:
unordered_map<int,int>ump;
unordered_map<char,int>ump;
unordered_map<string,int>ump;
增加元素方法(直接访问下标赋值):

ump[1000000009] = 56  
ump[‘t’]=123  
ump[“asdfas”]=565

方法:

常用方法与map相同  
ump.find(x):find是查找是否存在。  
ump.count(x):count是查找键为x的数量。(等同于查找x是否存在)  
ump.empty():判断是否为空  
ump.size():容器内元素数量  
ump.insert(x):x必须为对的形式。可以为pair的形式,通过make_pair创建。  
ump.erase(x):将键值为x的元素删除。  
ump.clear():清空unordered_map

迭代器:

与map相同,只是遍历的unordered_map是无序的

multimap

multimap容器保存的是有序的键/值对,顺序按第一关键字,第一关键字相同时,越早插入的元素越靠前。此容器可以保存重复的元素。由于能保存重复的元素,所以multimap中的元素不能通过下标访问。只能通过迭代器。  
如multimap中含有键值对(1,6)(1,5)(2,3)(1,5),遍历后输出顺序为:  
1 6  
1 5  
1 5  
2 3

方法:

由于键值可以重复,所以有些方法不适用  
mmp.insert(x):x必须为对的形式。可以为pair的形式,通过make_pair创建。  
mmp.erase(x):若x为键值,所有键值为x的元素都被删除,若x为迭代器,删除迭代器指向的元素  
mmp.count(x):返回有多少个键值为x的元素  
mmp.clear():清空multimap

练习题C 查字典

题目描述

全国英语四级考试就这样如期到来了,可是小Y依然没有做好充分的准备。为了能够大学毕业,可怜的小Y决定作弊。(太胆大妄为了,不怕被学校开除!!)  
小Y费尽心机,在考试的时候夹带了一本字典进考场。但是现在的问题是,考试的时候可能有很多单词要查,小Y能不能来得及呢。

输入描述

第一行一个整数N,表示字典中一共有多少单词(N<=10000)。  
接下来每两行表示一个单词,其中: 第一行是一个长度<=100的字符串,表示这个单词,全部小写字母,单词不会重复。  
第二行是一个整数,表示这个单词在字典中的页码。  
接下来一行是一个整数M,表示要查的单词数(M<=10000)。  
接下来M行,每行一个字符串,表示要查的单词,保证在字典中存在。

输出描述

M行,每行一个整数,表示第i个单词在字典中的页数。

输入样例
2
scan
10
word
15
2
scan
word
输出样例
10
15

练习题D 分类

题目描述

仓库里面堆积着很多的货物。小可放假归来,发现仓库里多了许多的货物。  
小可作为仓库管理员,需要对新多出来的货物进行分类整理。但是这段时间多出来的货物太多了,你能帮小可整理一下吗?

输入描述

第一行一个正整数T(1≤T≤10),代表有T组数据。  
对于每组数据,第一行有一个正整数n,代表有n条入库记录。  
接下来有n行入库记录。  
每个入库记录由字符串a,b和一个正整数m(1≤m≤100)组成,a是货物名,b是货物来源,m是数量。这两个字符串的长度都不长于80。

输出描述

请输出合并整理后格式正确的货物统计表。格式为:  
把货物按照来源地分类,来源地按照字典序排序输出。每个来源地都有下级分类。  
每个来源地下级分类中,每一行输出三个空格,一个|,四个-,用来保持缩进。子分类中,将来源地是此来源地的货物按照字典序排序,每个货物后面有一个括号,里面写货物的总数量。具体格式参考样例

输入样例
1
5
pencil shandong 3
eraser guangdong 1
water sichuan 1
eraser guangdong 3
water guangdong 1
输出样例
guangdong
 |----eraser(4)
 |----water(1)
shandong
 |----pencil(3)
sichuan
 |----water(1)

练习题E 信息筛选

题目描述

小可在服务器上维护了一个字典库,里面存放了很多单词信息。
但是使用的时间长了,难免会出现很多的冗余信息。于是小可打算着手去整理这个字典库。
小可认为,如果一个字典中的单词,能够通过重新排列字母变成另一个字典中的单词,那么这个单词就是冗余的。比如ride和dire都在字典中,那么这两个都是冗余的。
当然,我们进行比较的时候,忽略字母大小写。也就是说如果字典中有ride和DiRe,这两个单词依旧都是冗余的。

输入描述

若干行单词,都是由大写字母或者小写字母构成。长度不超过80。以#结束输入。

输出描述

按字典序顺序输出非冗余的单词。

输入样例
ssy
DiRe
My
would
ride
SHOULD
Yss
#
输出样例
My
SHOULD
would

练习题F 玩具箱

题目描述

小可获得了一个玩具箱,他买了许多玩具放在玩具箱里。有一天,达达来找小可玩,发现玩具箱里的玩具没有分类,十分杂乱,所以就替小可给玩具箱分类。每一个玩具有一个种类值 c i c_i ci,有一个价格值 p i p_i pi。最开始,达达将玩具箱置空,接下来达达要操作n次。达达一共有三种操作:  
1 c p表示将种类值为c,价格值为p的玩具塞入玩具箱。  
2 c表示将种类值为c的玩具全部删除,数据保证删除时玩具箱中一定存在。  
3 c表示计算种类值为c的玩具的数量。

输入描述

第一行输入n,表示操作的次数。  
接下来n行每行一个操作,格式如题面所示。

输出描述

对应每个3操作,输出对应的值  
n次操作后,按照顺序输出玩具箱中的所有玩具的种类值和价格值,每行对应一个玩具。顺序定义:优先种类值从小到大,若种类值相同,则按照玩具加入玩具箱的先后输出。

数据范围

1<=n<=100000,1<= c i c_i ci, p i p_i pi<= 1 0 9 10^9 109

输入样例
8
1 2 3
1 2 2
1 3 5
1 3 4
3 2
3 3
1 1 6
2 2
3 2
输出样例
2
2
0
1 6
3 5
3 4

set

功能:元素去重,可以按照从小到大的顺序进行排序。  
集合是由一些不重复的数据组成的。比如{1,2,3}就是一个有1,2,3三个元素的集合。C++中的集合可以支持高效的插入、删除、查询操作。  
这三个时间复杂度都为O(logn)  
头文件:  
注意:必须添加using namespace std;  
构造一个set的语句为:sets;  
这样就定义了一个类型为T,名为s的集合。  
插入操作:insert(),如果集合中已经存在了某个元素,再次插入不会产生任何效果,集合中不会出现重复元素。  
删除操作:erase(),删除集合中一个元素,集合中不存在这个元素,不进行任何操作。查找元素:count(),如果集合中存在要查找的元素,返回1,否则返回0。  
遍历元素:使用迭代器。迭代器类似于指针,可以遍历集合中的内容。  
清空:clear();

set迭代器

迭代器定义:
set<int>::iterator it;
set<char>::iterator it;
set<string>::iterator it;
set迭代器特性:

set是有序的,insert后自动排序  
set的迭代器it取值需要使用*  
set的迭代器只能++,–,不能±数值

unordered_set

头文件<unordered_set>
unordered_set是和set类似的STL容器,无序且去重。  
unordered_set底层实现是哈希表,增删查均摊复杂度O(1)

定义方法:
unordered_set<int>use;
unordered_set<char>use;
unordered_set<string>use;
方法:

use.find(x):find是查找x是否存在。  
use.count(x):返回元素x的数量。(有为1,没有为0)  
use.size():容器内元素数量  
use.insert(x):插入元素x  
use.erase(x):将值为x的元素删除。  
use.clear():清空unordered_set

迭代器定义:
unordered_set<T>::iterator it;

multiset

multiset是和set类似的STL容器,有序且不去重。

定义方法:
multiset<int>mse;
multiset<char>mse;
multiset<string>mse;
方法:

mse.find(x):返回查到的第一个元素值为x的迭代器  
mse.count(x):返回元素x的数量。  
mse.size():容器内元素数量  
mse.insert(x):插入元素x 
mse.erase(x):将值为x的元素全部删除。  
mse.clear():清空multiset  
mse.lower_bound(x):返回第一个值等于大于x的元素的迭代器  
mse.upper_bound(x):返回第一个值大于x的元素的迭代器

迭代器定义:
multiset<T>::iterator it;

练习题G 集合的并

题目描述

现在有两个集合,计算两个集合的并,即{A}+{B}。注:{A}+{B}中不允许出现重复元素,但是{A}与{B}之间可能存在相同元素。

输入描述

多组测试数据。每组数据包含三行。  
第一行为两个正整数n,m。分别表示两个集合的元素数量。  
第二行为第一个集合元素、第三行为第二个集合元素。

输出描述

输出两个集合并后的元素。

输入样例
1 2
1
2 3
1 2
1
1 2
输出样例
1 2 3
1 2

练习题H 修补道路

题目描述

小可家门口的路历经沧桑,已经不复平坦,变得坑坑洼洼的。  
于是小可拜托达达找了一个施工队来修补道路。施工队把这个道路分成了 n段,然后测量了这n段各自的高度。  
施工队的人对小可说:“我们现在要通过两种方式按段修复这条道路:

  1. 对有些路段填充一些材料,增加x高度。
  2. 对有些路段削减掉x的高度。 
      
    当然有的路段我们可能什么都不做。”  
    x是一个固定值,小可并不知道具体是多少。但是小可想知道通过这种方式,有没有可能让这个道路重新变得平坦。
输入描述

第一行一个正整数n(1≤n≤ 1 0 5 10^5 105)
第二行有n个整数 a i a_i ai(0≤ a i a_i ai 1 0 9 10^9 109),代表每段路的高度。

输出描述

如果可能重新变得平坦,输出"YES"。否则输出"NO"。平坦即为所有路段高度都相同。

输入样例
5
1 3 3 2 1
输出样例
YES

练习题I 包裹与数

题目描述

有一个用于装整数的包裹,一开始包裹里没有数,接下来有 n 次操作,每一次操作包含三种类型。  
1 x将一个整数x放入包裹  
2 x从包裹中取出一个值为x的数(保证包裹中有值为x的数)  
3 询问包裹中所有数中最接近的一对数(即差的绝对值最小的两个数,并输出这对数的差的绝对值)  
对于每次查询操作,输出对应的结果。如果查询时包裹中整数个数小于2个,输出2147483647

输入描述

输入的第一行包含一个整数n  
加下来n行,每一行可能是1 x、2 x、3这三种操作中的一种

输出描述

对于每一步查询操作,输出一行,为其对应的结果,即包裹中的所有数中最接近的一对数的差的绝对值。如果查询时包裹中整数个数小于2个,输出2147483647

数据范围

1<=n<= 1 0 5 10^5 105,1<=x<= 1 0 9 10^9 109

输入样例
9
1 2
1 5
3
1 7
3
2 5
3
2 7
3
输出样例
3
2
5
2147483647

pair

pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同。  
例如:

pair<int,int>t; //其中t包含了两个整数类型。
pair<int,string>a;//表示a中第一个元素是int型,第二个元素是string类型。
#### 初始化:
pair<string,string>a(“James”,”Joy”);//直接初始化

如果有三个属性的话,其实也是可以用pair的,极端的写法   pair<int,pair<int,int> >写法极端。  
(后边的两个>之间要有空格,否则就会是>>位移运算符 )

用法
  1. 对于pair类,由于它只有两个元素,分别名为first和second,因此直接使用普通的点操作符即可访问其成员。
pair<string,string>a(“Lily”,”Poly”);
cout<<a.first<<" "<<a.second; //a.first返回Lily,a.second返回Poly
  1. 生成新的pair对象,可以使用make_pair对已存在的两个数据构造一个新的pair类型。
pair<int,string>newone=make_pair(1,”abcd”);
  1. pair比较数据大小优先按照first比较,其次按照second比较,都默认升序。
  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值