C++常用STL讲解
关于STL(标准模板库)
Standard Template Library,缩写:STL
STL是一个C++软件库,里面包含算法(algorithms)、容器(containers)、函数(functions)、迭代器(iterators)
C语言版本
#include<stdio.h>
int main(){int a,b;scanf("%d%d",&a,&b);printf("%d",a+b);return 0;
}
C++版本
#include<bits/stdc++.h>
using namespace std;
int main(){int a,b;cin>>a>>b;cout<<a+b;return 0;
}
C++也可以兼容C语言
#include<bits/stdc++.h>
using namespace std;
int main(){int a,b;scanf("%d%d",&a,&b);printf("%d",a+b);return 0;
}
C++中的引用
#include<bits/stdc++.h>
using namespace std;void swap2(int &a,int &b){int c=a;a=b;b=c;
}int main(){int a,b;cin>>a>>b;swap2(a,b);//交换两个数的值cout<<a<<""<<b;return 0;
}
引用是C++新增的内容,就同C语言的指针一样重要,但它的指针更加方和易用,有时候甚至是不可或缺的。同指针一样,引用能够减少数据的拷贝,提高数据的传递效率。
字符串(String)
String是STL中的一个重要的部分,主要用于字符串处理。可以使用输入输出流方式直接进行String读入输出,类似于C语言中的字符数组,由C++的算法库对String类也有着很好的支持,大多时候字符串处理的问题使用String要比字符数组更加方便。
博客推荐:https://www.cnblogs.com/nanyangzp/p/3607534.html
字符串(String)
创建String类型变量
- String s;直接创建一个空的(大小为0)的String类型变量s
- String s = *char;创建String时直接用字符串内容对其赋值,注意字符串要用双引号“”
- String s(int n,char c);创建一个String,由n个c组成,注意c是字符型要用单括号‘ ’
读入String
- cin>>s;读入s,遇到空格或回车停止,无论原先s是什么内容都会被新读入的数据替代
- getline(cin,s);读入s,空格也同样会读入,直到回车才会停止
输出String
- cout<<s;将s全部输出到一行(不带回车)
赋值、比较、连接运算符:
赋值运算符:=将后面的字符串赋值给前面的字符串O(n)
比较运算符:== != < <= > >=比较的是两个字符串的字典序大小O(n)
连接运算符:+ +=将一个运算符加到另一个运算符后面O(n)
s[index]返回字符串s中下标为index的字符,String中下标也是从0开始O(1)
s.substr(p,n)返回从s的下标p开始的n个字符组成的字符串,如果n省略就取到底O(n)
s.length()返回字符串的长度O(1)
s.empty()判断s是否为空,空返回1,不空返回0,O(1)
s.erase(p0,len)删除s中从p0开始的len个字符,如果len省略就删到底O(n)
s.erase(s.begin()+i)删除下标为i个字符O(n)
s1.insert(p0,s2,pos,len)后两个参数截取s2,可以省略O(n)
s.insert(p0,n,c)在p0处插入n个字符c O(n)
s1.replace(p0,len0,s2,pos,len)删除p0开始的len0个字符,然后在p0处插入串s2中从pos开始的len个字符,后两个参数可以省略O(n)
s1.find(s2,pos)从前往后,查找成功时返回第一次出现的下标,失败返回string::npos的值(-1)O(n*m)
s1.rfind(s2,pos)从pos开始从后向前查找字符串s2中字符串在当前串后边第一次出现的下标O(n*m)
动态数组(vector)
vector容器是STL中最常用的容器之一,它和array容器非常类似,都可以看做是对C++普通数组的“升级版”。不同之处在于,array实现的是静态数组(容量固定的数组),而vector实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector会动态调整所占用的内存空间,整个过程无需人工干预。
博客推荐:http://blog.csdn.net/w_linux/article/details/71600574
- 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)
vector创建代码样例:
//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]默认为0vector<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;
}
int main(){vector int v;for(int i=1;i<=5;i++)v.push_back(i);//向动态数组中插入1~5cout<<v.size()endl;//输出数组的大小,有几个值for(int i=0;i<5;i++)cout<<v[i]<<" ";//输山v[0]~v[4],也就是1~5cout<<endl;v.clear();//将v清空,此时size为0v.resize(10);//为v重新开辟大小为10的空间,初始为0for(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]<<" ";//使用下标访问的方法遍历vcout<<endl;for(auto i=v.begin();i!=v.end();i++)cout<<i<<" ";//使用迭代器,从v.begin()到v.end()-1cout<<endl;for(auto i:v)//使用C++新特性循环遍历v,如果需要改变i的值,还需要在前面加上&cout<<i<<" ";cout<<endl;return 0;
}
关于迭代器(iterator)
vector<int>::iterator it=v.begin();等价于auto it=v.begin();
在这里it类似于一个指针,指向v的第一个元素
it等价于&v[0]
*it等价于v[0]
it也可以进行加减操作,例如it+3指向第四个元素
it++后it指向的就是v的第二个元素(v[1])了
队列(queue)
queue只能在容器的末尾添加新元素,只能从头部移除元素。
博客推荐:https://www.cnblogs.com/hdk1993/p/5809180.html
创建方法:
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)
优先队列(priority_queue)
priority_queue中出队顺序与插入顺序无关,与数据优先级有关,本质是一个堆
博客推荐:https://blog.csdn.net/qq_41822647/article/details/88899915
创建方法:
priority_queue<Type, Container, Functional>
// Type:数据类型
// Container:存放数据的容器,默认用的是 vector
//Functional:元素之间的比较方法,当type可以比较时后两个可以省略
使用方法:
- pq.push(item):在pq中添加一个元素 O(logn)
- pq.top():获取pq最大的元素 O(1)
- pq.pop():使pq中最大的元素出队 O(logn)
- pq.size():获取pq中元素个数 O(1)
- pq.empty():判断pq是否为空 O(1)
样例:
#include<bits/stdc++.h>
using namespace std;
int main(){priority_queue<int> pq;//priority_queue<int,vector<int>,greater<int>> pq;pq.push(1);pq.push(3);pq.push(2);while(!pq.empty()){cout<<pq.top()<<endl;pq.pop();}return 0;
}
Output:
3
2
1
#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;
}
Output:
3 2
2 1
1 3
priority_queue中存的元素如果是结构体这样无法进行比较的类型,必须要重载运算符<,相当于先使得优先队列中的元素可以进行比较再建立pq,否则直接建优先队列是会报错的
集合(set)
集合(set)是一种包含对象的容器,可以快速地(logn)查询元素是否在已知几集合中。
set中所有元素是有序地,且只能出现一次,因为set中元素是有序的,所以存储的元素必须已经定义过[<]运算符(因此如果想在set中存放struct的话必须手动重载[<]运算符,和优先队列一样)
与set类似的还有:
- multiset元素有序可以出现多次
- unordered_set元素无序只能出现一次
- unordered_multiset元素无序可以出现多次
博客推荐:https://www.cnblogs.com/zyxStar/p/4542835.html
集合(set)
建立方法:
*set<Type> s;
multiset<Type> s;
unorded_set<Type> s;
unorded_multiset<Type> s;
如果Type无法进行比较,还需要和优先队列一样定义<运算符
遍历方法:
for (auto i:s)cout<< i <<" ";
//和vector的类似
使用方法:
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)
映射(map)
map是照特定顺序存储由key和value的组合形成的元素的容器,map中元素按照key进行排序,每个key都是唯一的,并对应着一个value,value可以重复。
map的底层实现原理与set一样都是红黑树。
与map类似的还有unordered_map,区别在于key不是按照顺序排序
博客推荐:https://www.cnblogs.com/panweiwei/p/6657583.html
建立方法:
map<key,value> mp;
unordered_map<key,value> mp;
遍历方法:
for(auto i:mp)
cout<<i.first<<’ '<<i.second<<endl;
map的常用函数:
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()0(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)
unordered的作用:
set和map都可以在前面加上unorder_使得内部的元素改成不按顺序存储的,其余的功能都不改变,虽然无法顺序存储,但底层原理是hash,可以使得所有的查询、修改、删除操作都变成O(1)复杂度
二进制有序集(bitset)
bitset是一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1bit空间。
博客推荐:https://blog.csdn.net/qq_52023825/article/details/122409539
建立方法:
- bitset<n> b;//建立一个可以存n位二进制的有序集
- bitset<n> b(unsigned long u);//坐标从后往前计数,高位在前
- bitset<n> b(String s);//将由‘0’和‘1’组成的字符串赋值给支持所有位操作:| |= & &= << <<= >> >>=
- cout<< b;//bitset可以直接用cout输出b[index];//可以用下标操作符来读或写某个索引位置的二进制位
//比如bitset<10>b(5);等价于bitset<10>b(“1010”);
//其中cout<<b输出0000001010
//for(int i=0;i<10;i++)cout<<b[i];输出0101000000
使用方法:
b.count();//count函数用来求bitset中1的位数
b.size();//size函数用求求bitset的大小
b.any();//any函数检否bitset中是否有1
b.none();//none函数检查bitset中是否没有1
b.all();//all函数检查bitset中是全部为1
foo.flip();//flip函数不指定参数时,将bitset每一位全部取反
foo.set();//set函数不指定参数时,将bitset的每一位全部置为1
foo.reset();//reset函数不传参数时将bitset的每一位全部置为0
String s = foo.to_string();//将bitset转换成String类型
unsigned long a=foo.to_ulong();//将bitset转换成unsigned long类型
unsigned long long b=foo.to_ullong();//将bitset转换成unsigned long long类型
常用函数:
- max(val1,val2):返回更大的数
- min(val1,val2):返回更小的数
- swap(type,type):交换两者的值,可以是两个值也可以是两个STL的容器
排序函数(sort)
sort(first, last, compare)
- first:排序起始位置(指针或 iterator)
- 1ast:排序终止位置(指针或iterator)
- compare:比较方式,可以省略,省略时默认按升序排序,如果排序的元素没有定义比较运算(如结构体),必须有compare
sort排序的范围是[first,last],时间为 O(nlogn)
sort基本样例:
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b){return a>b;
}
int main(){int arr[]={3,2,5,1,4};sort(arr,arr+5);sort(arr,arr+5,greater<int>());sort(arr,arr+5,cmp);sort(arr,arr+5,[](int a,int b){returm a>b;});return 0;
}
去重函数(unique)
unique(first, last):
- [first,last]范围内的值必须是一开始就提前排好序的
- 移除[first,last]内连续重复项
- 去重之后的返回最后一个元素的下一个地址(迭代器)
#include<bits/stdc++.h>
using namespace std;
int main(){int arr[]{3,2,2,1,2},n;sort(arr,arr+5);//需要先排序n=unique(arr,arr+5)-arr;//n是去重后的元素个数return 0;
}
二分函数(lower_bound/upper_bound)
lower_bound(first,last,value)
first:查找起始位置(指针或 iterator)
last:查找终止位置(指针或iterator)
value:查找的值
lower_bound 查找的范围是[first,last],返回的是序列中第一个大于等于value的元素的位置,时间为 O(logn)
[first,last]范围内的序列必须是提前排好序的,不然会错
如果序列内所有元素都比value小,则返回last
upper_bound(first, last, value)
- upper_bound与 lower_bound相似,唯一不同的地方在于upper_bound查找的是序列中第一个大于value的元素
二分函数样例:
int main(){int arr[]={3,2,5,1,4};sort(arr,arr+5);//需要先排序cout<< *lower_bound(arr,arr+5,3);//输出数组中第一个大于等于3的值return 0;
}
next_permutation
next_permutation(first,last)
用于求序列[first,last]元素全排列中一个排序的下一个排序
#include<bits/stdc++.h>
using namespace std;
int main(){int a[3] {0,1,2};do{for(int i=0;i<3;i++)cout<<a[i]<<' ';cout<<endl;}while(next_permutation(a,a+3));return 0;
}
C++常用STL讲解相关推荐
- 常用传感器讲解七--红外警报传感器(KY-008)
常用传感器讲解七–红外警报传感器(KY-008) 具体讲解 这个是一种由身体运动触发的设备,可以使用它来检测人,动物,汽车--经过某个区域时的情况.这是一个基于LASER发射器的设备,该发射器不断向光 ...
- 常用传感器讲解十--光传感器根据亮度安排灯光
常用传感器讲解十–光传感器根据亮度安排灯 具体讲解 接线 我有一个光敏电阻连接到模拟引脚0(任何模拟引脚都可以工作)和面包板右侧的5V电压.它通过接地的1K欧姆电阻器运行.我将面包板另一侧的LED(任 ...
- 常用传感器讲解八--土壤湿度传感器(XH-M214)
常用传感器讲解八–土壤湿度传感器(XH-M214) 具体讲解 土壤水分传感器测量土壤水分随土壤电导率的变化而变化(土壤电阻随干旱而增加).在传感器的两个电极之间测量电阻. 当超过可调整的阈值时,比较器 ...
- 常用传感器讲解五--声音传感器-(KY-037)
常用传感器讲解五–声音传感器-(KY-037) 具体讲解 该模块由一个用于检测声音的灵敏电容麦克风和一个放大电路组成.该模块的输出既是模拟的又是数字的.数字输出用作键,并且它当声音强度达到某个阈值时激 ...
- 常用传感器讲解十四--障碍探测器(KY-032)
常用传感器讲解十四–障碍探测器(KY-032) 具体讲解 KY-032避障传感器是为轮式机器人设计的可调节距离的红外接近传感器.也称为AD-032. 传感器的检测距离为2cm至40cm,可以通过旋转电 ...
- 常用传感器讲解十七--簧片开关传感器(KY-036)
常用传感器讲解十七–簧片开关传感器(KY-036) 具体讲解 KY-025簧片开关模块是一种小型电气开关,通常由接近磁场通过施加的磁场进行操作. 该模块具有数字和模拟输出.微调器用于校准传感器的灵敏度 ...
- 常用传感器讲解十一--light cup(KY-027)
常用传感器讲解七–light cup(KY-008) 具体讲解 KY-027魔术灯杯模块是一组两块板,每块板都有一个led和一个水银倾斜开关.使用PWM驱动每个模块上的LED,可以实现倾斜时将光从一个 ...
- 常用传感器讲解十三--霍尔效应传感器(KY-003)
常用传感器讲解十三–霍尔效应传感器(KY-003) 具体讲解 霍尔效应传感器是根据是否存在磁场来改变其输出的传感器.这意味着霍尔效应传感器产生的输出信号是其周围磁场密度的函数.当其周围的磁通密度超过某 ...
- 常用传感器讲解十五--触摸传感器(KY-036)
常用传感器讲解十五–触摸传感器(KY-036) 具体讲解 这个比较简单,就是触摸后给个信号 电路连接 在Arduino上将VCC引脚连接到5V. 将GND连接到Arduino的GND. 将OUT连接到 ...
最新文章
- 数据仓库中宽表的设计原则_实际项目中交互设计原则的运用
- 中国率先发布全球首份车路协同技术白皮书!清华百度联手,突破自动驾驶规模落地瓶颈...
- oracle自动imp脚本
- 混淆矩阵怎么看_道理我都懂,但是神经网络反向传播时的梯度到底怎么求?
- android和web api接口,WebService和Webapi的区别
- HTML中常用知识点整理
- 让VS2010添加新类时自动添加public关键字(来自dudu博文)
- 调参方法论:如何提高机器学习模型的性能?
- 洛谷P1494 [国家集训队]小Z的袜子
- 深圳大学二本计算机软件,深圳大学是几本(深圳大学是一本还是二本)
- Spring Cloud Hystrix 进行服务熔断设置时,报错找不到对应的服务熔断方法
- 3.6 Spark安装与体验
- 快速 二进制,八进制,十进制,十二进制转换 .源码,反码,补码,
- 小学计算机画图课件第一册,小学信息技术有趣的画图工具PPT课件.ppt
- 为什么项目验收前的总是非常忙乱?
- 机器学习和深度学习资料汇总【02】
- 营业执照注册编码 15与18位的java实现
- 通过AWS云平台 构建云上勒索病毒防护体系,轻松保护数据完整性
- 使用KCP 加速游戏消息,让全球玩家流畅联网
- Spring和Quartz实现的定时任务调度
热门文章
- ubuntu - 安装QQ国际版
- 华为网络篇 使用SSH方式登陆路由器-06
- 深入理解Serdes 结构之 结构概览
- 程序洞穴生成六(Procedural Cave Generation)
- opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较
- 中兴测试软件可以看sip信令吗,中兴光猫FTTH_SIP协议开通调试现场配置指导书
- 华为HCIA-Datacom 学习笔记-------第一篇
- Java:Java 8 函数式接口FunctionalInterface
- 2021年P气瓶充装报名考试及P气瓶充装考试内容
- 低级鼠标钩子WH_MOUSE_LL