C++刷题常用STL容器总结

举报
野猪佩奇996 发表于 2022/01/23 02:31:14 2022/01/23
3.5k+ 0 0
【摘要】 文章目录 总序1.vector头文件定义元素访问常用函数使用场景 2.set头文件定义元素访问常用函数使用场景扩展 3.string头文件&定义内容访问常用函数 4.ma...

总序

(1)只有vector、string、deque是可以用sort(默认从小到大,如果要改优先级则加cmp作为第三个参数),而set和map是用红黑树实现(自动排序)。
(2)只有vector和string能直接对迭代器加减某个数,如str.begin()+3——但注意起始advance(it,num)可以实现将迭代器it向后移动num位,如果num是负数则是向前移动;
注意string要用头文件< string >(和头文件<string.h>不一样)。
(3)C++11的unordered_set去重但不排序(如果不去重则用multiset),unordered_map不按key排序(速度比map快很多)。
(4)如果遇到一些不熟悉的stl,可以直接查询c++的官方文档,如map的count,里面有解释也有对应的栗子。

1.vector

(1)动态数组,方便动态扩容,方便的变量初始化(int类型默认初始化为0,bool默认初始化为false)。
(2)可以用来实现邻接表(结点数太多的图)。
(3)有些场合需要根据一些条件把部分数据输出在同一行,数据中间用空格隔开。由于输出数据的个数不确定,为了更方便地处理最后一个满足条件的数据后面不输出额外的空格,可以先用vector记录所有需要输出的数据,然后一次性输出

头文件

#include<vector>
using namespace std;

  
 

定义

//typename可以是基本数据类型/其它标准STL容器/自定义结构体
vector<typename>name;
vector<int>v1;

vector<vector<int> >v2;//两个维度都是动态(数组)的
vector<int> vi[100];//每个vi[i]都是一个vector容器

  
 

元素访问

//1.下标访问
v[i];//和v.begin()+i是等价的
//2.迭代器访问
vector<typename>::iterator it;
auto it;//另一种迭代器简易定义方法
for(auto it=v.begin();it!=v.end();it++)
	cout<<*it;
for(int i=0;i<5;i++)
	printf("%d ",*(it+i));
//只有vector和string的迭代器it可以进行算术运算进行访问元素。

  
 

注意要支持C++11才能使用上面的auto这种写法。

常用函数

函数 说明
push_back(x) 将元素x添加到容器末尾
pop_back() 删除容器末尾元素
size() 获得容器大小
clear() 清空元素
insert(it,x) 在it处插入一个元素x
erase(it) 删除it处的元素
erase(first,last) 删除[first,last)区间内的元素

使用场景

  • 元素个数不确定
  • 用于实现邻接表存储图

2.set

内部自动有序且不含重复元素的集合

头文件

#include<set>
using namespace std;

  
 

定义

set<typename> name;

  
 

元素访问

for(auto it=v.begin();it!=v.end();it++)
	cout<<*it;

  
 

常用函数

函数 说明
insert(x) 将元素x插入set容器中,并自动递增排序和去重
find(value) 查找值为value的元素,返回对应迭代器
erase(it) 删除it处的元素,通常结合find函数使用
erase(first,last) 删除[first,last)区间内的元素
size() 返回容器大小
clear() 清空容器

使用场景

  • 自动去重并按升序排序

扩展

  • 需要元素不唯一,使用multiset
  • 需要元素不排序,unordered_set(内部以散列代替了set内部的红黑树)

3.string

字符串,可以替换为C语言版本的字符数组(str.c_str()😉

头文件&定义

#include<string>
using namespace std;
string str;

  
 

内容访问

///1.下标访问
str[i]
//2.输出输出只能用cin和cout,除非转化为字符数组
//3.迭代器访问

  
 

常用函数

函数 说明
operator+= 字符串拼接
compare operator 按照字典序列比较大小
length()/size() 获得字符串大小
insert(pos,str) pos是int类型,表示在制定位置插入str
insert(it,first,last) 在it出插入[first,last)范围内的字符串
erase(it) 删除it处的元素
erase(first,last) 删除[first,last)范围内的元素
erase(pos,length) 删除pos位置开始的length个字符
clear() 清空字符串
substr(pos,len) 返回从pos位置开始len长度的字符串
string::npos 作为find函数未找到的判断依据
find(str) 返回str第一次出现的位置
replace(pos,len,str2) 从pos位置开始,长度为len的子串替换为str2

4.map

将任何基本类型映射到任何基本类型(包括STL容器)
可以用于hash散列(当元素个数比较多时,不适合用数组散列,就用map)
(1)需要建立字符(或字符串)与整数之间映射的题;
(2)判断大整数或其他类型数据是否存在的题目,可以将map当bool数组使用。

头文件及定义

#include<map>
using namespace std;
map<typename1,typename2> mp;

  
 

元素访问

//1.下标
mp['c']    mp[0]   mp["key"]
//2.迭代器
for(auto it=mp.begin();it!=mp.end();it++)
	cout<<it->first<<" "<<it->second;

  
 

常用函数

函数 说明
find(key) 返回键为key的映射的迭代器
erase(it) 删除it处的元素
erase(key) 删除key
erase(first,last) 删除[first,last)区间内的元素
size() 返回容器大小
clear 清空容器
count 返回对应的key值的个数,在map中自然就是0或者1了

使用场景

  • 散列表
  • 其他映射
    扩展
  • 多映射,即一个key对应多个value,使用mutimap
  • undered_map可以替代map,内部实现使用散列代替了map内部的红黑树实现,用于处理只映射而不需要按key来排序的需求,速度快。

5.queue

队列,先进先出的容器,常用语广度优先遍历BFS

头文件及定义

#include<queue>
using namespace std;
queue<typename>name;

  
 

常用函数

函数 说明
push(x) 元素x入队列
front() 访问队列的首元素
back() 访问队列的尾元素
pop() 队首元素出队
empty() 检测是否为空队列
size() 队列大小

使用场景

  • BFS
    另外,需要注意使用front(),back(),pop()函数前,必须判断是否为空队列(empty函数)
    扩展
  • deque(double end queue,双端队列)首位皆可插入和删除u
  • priority_queue,使用堆实现的默认将当前队列最大元素置于队首的容器

6.priority_queue

优先队列,默认情况下是将队列中最大元素置于队首,优先级可以自定义。每次进行push().pop()操作,底层的数据结构堆(heap)都会随时调整调整,使优先级最高的元素永远在队首。

头文件&定义

#include<queue>
using namespace std;
priority_queue<typename> name;

  
 

常用函数

函数 说明
push(x) 将元素x入队
top() 访问队首元素
pop() 将队首元素出队
empty() 检测是否为空队列
size() 返回队列大小

优先级设定

基本数据类型(int ,double,char)默认数字大或字典序大的优先级高。

priority_queue<int,vector<int>,greater<int>> q;

  
 
  • greater表示这个数字越小,优先级越高
  • less表示数字越大,优先级越高(默认情况)
    vector表示底层数据堆(heap)的容器
    结构体优先级设置
#include<iostream>
#include<string>
#include<queue>
using namespace std;
struct fruit{
	string name;
	int price;
	friend bool operator < (fruit f1,fruit f2);
		return f1.price>f2.price;
	}
}f1,f2,f3;
int main(){
	priority_queue<fruit> q;
	f1.name="桃子";
	f.price=3;
	f1.name="梨子";
	f.price=4;
	f1.name="苹果";
	f.price=1;
	q.push(f1);
	q.push(f2);
	q.push(f3);
	cout<<q.top().name<<" "<<q.top().price<<endl;
	return 0;
}

  
 

使用场景

(1)priority_queue可以解决一些贪心问题,也可以用于dijkstra算法的顶点选择(优化)中(因为优先队列的本质是堆)。
(2)注意使用top函数之前判断队列是否为空(empty()函数)。

7.stack

栈,先今后出

头文件及定义

#include <stack>
using namespace std;
stack<typename> name;

  
 

常用函数

函数 说明
push(x) 元素x入栈
top() 获取栈顶元素
pop() 栈顶元素出栈
empty() 检测stack是否为空
size() 获取栈的大小

使用场景

递归模拟,防止递归深度过深,DFS模拟

8.pair

**头文件及使用

#include<utility>//或者偷懒用头文件<map>,因为map包含了utility
using namespace std;
//map实现中设计pair,使用map时自动添加了该头文件

pair<typename1,typename2> name;
paif<string,int> p("hahahah",7);
make_pair("haha",4);
cout<<p.first<<" "<<p.second;

  
 

(1)用来代替二元结构体及其构造函数,省时。
(2)作为map的键值对来进行插入。如下栗子:

map<string,int>mp;
mp.insert(make_pair("guoguo",1));
mp.insert(pair<string,int>("guoguo2",2);
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++){
	cout<<it->first <<" "<<it->second<<endl;
}

  
 

9.algorithm常用函数

algorithm头文件下的常用函数有max()min()abs()(这个abs的x必须是整数),浮点数的绝对值要用math头文件的fabs()
swap(x,y)交换x和y变量的值。
reverse(x,y)将数组指针/容器的迭代器在[it,it2)之间的元素进行反转。
利用#include< algorithm >头文件的next_permutation()函数。

#include <iostream>
#include <algorithm>
using namespace std;
int sum=0;
int main()
{
	int a[6]={1,2,3}; 
	do{
		for(int i=0;i<3;i++)
			cout<<a[i];
		cout<<endl;
		sum++;
	}while(next_permutation(a,a+3));
	cout<<sum;
	system("pause");
}

  
 

(1)使用循环是因为next_permutation在已经到达全排列的最后一个时会返回false,这样会方便退出循环;
(2)使用do…while语句而不使用while语句是因为序列1 2 3本身也需要输出,而如果用while语句会直接跳到下一个序列(1 3 2)再输出(即少了一个1 2 3)。
在这里插入图片描述
关于lower_boundupper_bound就复习下这个:https://andyguo.blog.csdn.net/article/details/112369996
最后一个是

($)sort函数排序:

(1)基本数据类型数组/string型
如对int/double/char型数组排序,或对string字符串排序——sort(s.begin(),s.end());
(2)结构体数组
sort排序默认是从小到大,如果要从大到小排序:(注意functional的头文件):

#include<algorithm>
#include<functional>
int a[100000];
sort(a,a+n,greater<int>());
//或者
int cmp(int a,int b){return a>b;}
sort(a,a+n,cmp);

  
 

符号重载的node结构体作为set的元素自动排序(按频率cnt降序,如cnt同则编号升序)
注意运算符重载在结构体中的写法:

struct node{
	int value,cnt;
	bool operator<(const node &a)const{
		return (cnt!=a.cnt)?cnt>a.cnt:value<a.value;
		//第一优先级:频率降次  第二优先级:编号
	}
};

  
 

(3)容器的排序
只有vector、string、deque是可以使用sort,而set、map是用红黑树实现,内部的元素自动排序了,所以不用sort。

附各容器操作:

vector, 变长数组,倍增的思想
    size()  返回元素个数
    empty()  返回是否为空
    clear()  清空
    front()/back()
    push_back()/pop_back()
    begin()/end()
    []
    支持比较运算,按字典序

pair<int, int>
    first, 第一个元素
    second, 第二个元素
    支持比较运算,以first为第一关键字,以second为第二关键字(字典序)

string,字符串
    size()/length()  返回字符串长度
    empty()
    clear()
    substr(起始下标,(子串长度))  返回子串
    c_str()  返回字符串所在字符数组的起始地址

queue, 队列
    size()
    empty()
    push()  向队尾插入一个元素
    front()  返回队头元素
    back()  返回队尾元素
    pop()  弹出队头元素

priority_queue, 优先队列,默认是大根堆
    size()
    empty()
    push()  插入一个元素
    top()  返回堆顶元素
    pop()  弹出堆顶元素
    定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;

stack,size()
    empty()
    push()  向栈顶插入一个元素
    top()  返回栈顶元素
    pop()  弹出栈顶元素

deque, 双端队列
    size()
    empty()
    clear()
    front()/back()
    push_back()/pop_back()
    push_front()/pop_front()
    begin()/end()
    []

set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列
    size()
    empty()
    clear()
    begin()/end()
    ++, -- 返回前驱和后继,时间复杂度 O(logn)

    set/multiset
        insert()  插入一个数
        find()  查找一个数
        count()  返回某一个数的个数
        erase()
            (1) 输入是一个数x,删除所有x   O(k + logn)
            (2) 输入一个迭代器,删除这个迭代器
        lower_bound()/upper_bound()
            lower_bound(x)  返回大于等于x的最小的数的迭代器
            upper_bound(x)  返回大于x的最小的数的迭代器
    map/multimap
        insert()  插入的数是一个pair
        erase()  输入的参数是pair或者迭代器
        find()
        []  注意multimap不支持此操作。 时间复杂度是 O(logn)
        lower_bound()/upper_bound()

unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表
    和上面类似,增删改查的时间复杂度是 O(1)
    不支持 lower_bound()/upper_bound(), 迭代器的++--

bitset, 圧位
    bitset<10000> s;
    ~, &, |, ^
    >>, <<
    ==, !=
    []

    count()  返回有多少个1

    any()  判断是否至少有一个1
    none()  判断是否全为0

    set()  把所有位置成1
    set(k, v)  将第k位变成v
    reset()  把所有位变成0
    flip()  等价于~
    flip(k) 把第k位取反

  
 

文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。

原文链接:andyguo.blog.csdn.net/article/details/104069065

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。