c++常用STL大总结

想了半天感觉写一些单个的stl专题过于麻烦,和网上的也差不多,不如写一篇总结,盘点一下主流的stl以及它们的作用,什么时候使用哪个比较好。

理想状态下,这篇文章看完之后你就能比葫芦画瓢去用

一、当你需要(对数据进行一对一映射)/(用数据A找数据B)的时候 ------使用map

1、介绍

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的处理能力。

Map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。

Map假如说类比于数组shuzu[maxn]=x,关键字A就像maxn的位置的数字,数据B就像x这个被记录的数值。

2、功能

Map的功能回事一对一映射的查找。它可以自动建立Key - value的对应。key 和 value可以是任意你需要的类型。

主要有以下几个功能:

根据key值快速查找记录,查找的复杂度基本是Log(N)。

快速插入、修改、遍历或删除Key -Value 记录。

3、基本操作

建立方法: map<key, value> mp; 

遍历方法: for(auto i:mp) cout<<i.first<<' '<<i.second<<endl;

mp.size():获取 mp 中元素个数 O(1)
mp.empty():判断 mp 是否为空 O(1)
mp.clear():清空 mp O(1)
mp.begin():返回 mp 中最小 key 的迭代器,和set一样,只可以用到--和++操作 O(1)
mp.end():返回 mp 中最大 key 的迭代器的后一个迭代器 O(1)
mp.find(key):在 mp 中查找⼀个 key 并返回其 iterator,找不到的话返回 s.end() O(logn)
mp.count(key):在 mp 中查找 key 的数量,因为 map中 key 唯⼀,所以只会返回 0 或 1 O(logn)
mp.erase(key): 在 mp 中删除 key 所在的项,key和value都会被删除 O(logn)
mp.lower_bound(item):返回 mp 中第一个key大于等于item的迭代器,找不到就返回mp.end() O(logn)
mp.upper_bound(item):返回 mp 中第一个key大于item的迭代器,找不到就返回mp.end() O(logn)
mp[key]:返回 mp 中 key 对应的 value。如果key 不存在,则返回 value 类型的默认构造器(defaultconstructor)所构造的值,并该键值对插⼊到 mp 中O(logn)
mp[key] = xxx:如果 mp 中找不到对应的 key 则将键值对 (key: xxx) 插⼊到 mp 中,如果存在 key 则将这个 key 对应的值改变为 xxx O(logn)

二、当你需要(先进后出)/(进了则准备出)的时候 ------使用stack

建立方法:stack<type> st;

top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。
push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。
push(T&& obj):以移动对象的方式将对象压入栈顶。这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。
pop():弹出栈顶元素。
size():返回栈中元素的个数。
empty():在栈中没有元素的情况下返回 true。
emplace():用传入的参数调用构造函数,在栈顶生成对象。
swap(stack<T> & other_stack):将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap() 可以使用。

三、当你需要(先进先出)/(进出强调加入时顺序)的时候 ------使用queue

1、基本操作

queue<type>q; 建立一个存放数据类型为type的队列q;

▸ q.push(item):在 q 的最后添加⼀个type类型元素item O(1)
▸ q.pop():使 q 最前⾯的元素出队 O(1)
▸ q.front():获取 q 最前⾯的元素 O(1) 
▸ q.size():获取 q 中元素个数 O(1)
▸ q.empty():判断 q 是否为空,空返回1,不空返回0 O(1)

四、当你需要(按照value将加入的元素进行实时排列)的时候 ------使用priority_queue

1、介绍

priority_queue<Type, Container, Functional>

// Type:数据类型

// Container:存放数据的容器,默认⽤的是 vector

// Functional:元素之间的⽐较⽅法,当type可以比较时后两个可以省略

2、大小堆

priority_queue<int> pq; ------默认为大根堆,输出顺序由大到小

priority_queue<int,vector<int>,greater<int> >pq; ------这样写可以把大的变小的,输出顺序由小变大

3、重载

priority_queue中存的元素如果是结构体这样无法进行比较的类型,必须要重载运算符<,相当于先使得优先队列中的元素可以进行比较再建立pq,否则直接建优先队列是会报错的。

#include<bits/stdc++.h>
using namespace std;
struct node
{
	int x,y;
};
bool operator <(node a,node b)
{
	return a.x<b.x;
}
int main()
{
	priority_queue<node> pq;
	pq.push({1,3});
	pq.push({3,2});
	pq.push({2,1});
	while(!pq.empty())
	{
		cout<<pq.top().x<<" "<<pq.top().y<<endl;
		pq.pop();
	}
	return 0;
 } 
 /*
 结果为 
 3 2
 2 1
 1 3
 */

4、基本操作

empty()      如果队列为空,则返回真
pop()    删除对顶元素,删除第一个元素
push()        加入一个元素
size()      返回优先队列中拥有的元素个数
top()     返回优先队列对顶元素,返回优先队列中有最高优先级的元素

 

五、当你需要(元素有序且需要查询 )的时候 ------使用set

1、介绍

集合(set)是一种包含对象的容器,可以快速地(logn)查询元素是否在已知几集合中。 set 中所有元素是有序地,且只能出现⼀次,因为 set 中元素是有序的,所以存储的元素必须已经定义 过「<」运算符(因此如果想在 set 中存放 struct 的话必须⼿动重载「<」运算符,和优先队列一样)

2、基本操作

建立方法:

set<Type>s; multiset<Type>s;

unorded_set<Type>s;

unorded_multiset<Type>s;

如果Type无法进行比较,还需要和优先队列一样定义<运算符

遍历方法:

for(auto i:s)cout<<i<<" "; //和vector的类似

排序:默认是从小到大

当然你也可以改成从大到小

struct intComp {
	bool operator() (const int& lhs, const int& rhs) const{
		return lhs > rhs;
	}
};

一些基本操作: 

s.insert(item):在 s 中插⼊⼀个元素 O(logn)
s.size():获取 s 中元素个数 O(1)
s.empty():判断 s 是否为空 O(1)
s.clear():清空 s O(n)
s.find(item):在 s 中查找⼀个元素并返回其迭代器,找不到的话返回 s.end() O(logn)
s.begin():返回 s 中最小元素的迭代器,注意set中的迭代器和vector中的迭代器不同,无法直接加上某个数,因此要经常用到--和++O(1)
s.end():返回 s 中最大元素的迭代器的后一个迭代器 O(1)
s.count(item):返回 s 中 item 的数量。在set中因为所有元素只能在 s 中出现⼀次,所以返回值只能是 0 或 1,在multiset中会返回存的个数 O(logn)
s.erase(position):删除 s 中迭代器position对应位置的元素O(logn)
s.erase(item):删除 s 中对应元素 O(logn)
s.erase(pos1, pos2):删除 [pos1, pos2) 这个区间的位置的元素 O(logn + pos2 - pos1)
s.lower_bound(item):返回 s 中第一个大于等于item的元素的迭代器,找不到就返回s.end() O(logn)
s.upper_bound(item):返回 s 中第一个大于item的元素的迭代器,找不到就返回s.end() O(logn)

六、当你啥也不需要,单纯想升级一下数组的时候 ------使用vector

1、介绍

vector 容器是 STL 中最常用的容器之一,它和 array 容器非常类似,都可以看做是对 C++ 普通数组的“升级版”。不同之处在于,array 实现的是静态数组(容量固定的数组),而 vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector 会动态调整所占用的内存空间,整个过程无需人工干预。

2、基本操作

vector<type>v 创建动态数组v,后面可以加{}或()进行初始化

type v[index] 获取v中第 index 个元素 O(1)
v.push_back(type item) 向v后⾯添加⼀个元素item O(1) 
v.pop_back() 删除 v 最后⼀个元素 O(1)
v.size() 获取 v 中元素个数,返回size_type类型 O(1)
v.resize(int n) 把 v 的⻓度设定为 n 个元素 O(n)
v.empty() 判断 v 是否为空,空返回1,不空返回0,O(1)
v.clear() 清空 v 中的元素 O(size)
v.insert(iterator it,type x)向迭代器it指向元素前增加一个元素x,O(n)
v.erase(iterator it) 删除向量中迭代器指向元素,O(n)
v.front()返回首元素的引用O(1)
v.back()返回尾元素的引用O(1)
v.begin()返回首迭代器,指向第一个元素O(1)
v.end()返回尾迭代器,指向向量最后一个元素的下一个位置O(1)

3、样例

//vector的创建
#include <bits/stdc++.h>
using namespace std;
int main()
{
    vector<int>v1;
    //创建一个存int类型的动态数组,int可以改成其它类型
    vector<double>v2{1,1,2,3,5,8};
    //创建一个存double类型的动态数组,长度为6,1 1 2 3 5 8分别存在v[0]~v[5]
    vector<long long>v3(20);
    //创建一个存long long类型的动态数组,长度为20,v[0]~v[19]默认为0
    vector<string>v4(20,"zzuacm");
    //创建一个存string类型的动态数组,长度为20,存的都是"zzuacm"
    vector<int>v5[3];
    //相当于存int的二维数组,一共3行,每行的列可变
    vector<vector<int>>v5{{1,2},{1},{1,2,3}};
    //存int的二维数组,行和列都可变,初始状态
    return 0;
}
//vector的基本操作
int main()
{
    vector<int>v;
    for(int i=1;i<=5;i++)
        v.push_back(i);//向动态数组中插入1~5
    cout<<v.size()<<endl;//输出数组的大小,有几个值
    for(int i=0;i<5;i++)
        cout<<v[i]<<" ";//输出v[0]~v[4],也就是1~5
    cout<<endl;
    v.clear();//将v清空,此时size为0
    v.resize(10);//为v重新开辟大小为10的空间,初始为0
    for(int i=0;i<v.size();i++)
        cout<<v[i]<<" ";//遍历每一个元素
    while(!v.empty())//当v还不空的话,去掉v的最后一个元素,等同于v.clear();
        v.pop_back();
    return 0;
}
//插入、删除和遍历
int main()
{
    vector<int>v{0,1,2,3,4};
    v.erase(v.begin()+3);//删除v[3],v变为{0,1,2,4}
    v.insert(v.begin()+3,666);//在v[3]前加上666,v变成{0,1,2,666,4}
    v.front()=10;//将v[0]改成10,等同于v[0]=10;
    v.back()=20;//将v[4]改成20等同于v[v.size()-1]=20;
    for(int i=0;i<v.size();i++)
        cout<<v[i]<<" ";//使用下标访问的方法遍历v
    cout<<endl;
    for(auto i=v.begin();i!=v.end();i++)
        cout<<*i<<" ";//使用迭代器,从v.begin()到v.end()-1
    cout<<endl;
    for(auto i:v)//使用C++新特性循环遍历v,如果需要改变i的值,还需要在前面加上&
        cout<<i<<" ";
    cout<<endl;
    return 0;
}

vector想看更多的就看这个吧 https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值