关于 STL(标准模板库)
Standard Template Library,缩写:STL
STL 是 个 一C++ 软件库, 包含算法(里面algorithms)、容 器(containers)、函数(functions)、迭代器(iterators)
字符串(string)
创建string类型变量string s;
直接创建一个空的(大小为0)的string类型变量s
string s=*char; 创建string时直接用字符串内容对其赋值,注意字符串要用双引号""
strings(int n,char c); 创建一个string,由n个c组成,注意c是字符型要用单括号’’
读入string
cin>>s; 读入s,遇到空格或回车停止,无论原先s是什么内容都会被新读入的数据替代。
getline(cin,s); 读入s,空格也同样会读入,直到回车才会停止
输出string
cout<<s; 将s全部输出到一行(不带回车)
string中的函数
动态数组(vector)
vector 容器是 STL中最常用的容器之一,它和 array 容器非常类似,都可以看做是对 C++普通数组的“升级版”。不同之处在于,array 实现的是 静态数组(容量固定 的数组),而vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,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]默认为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;
基本操作
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;
}
vector插入、删除、遍历
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++11新特性循环遍历v,如果需要改变i的值,还需要在前面加上&
cout<<i<<" ";
cout<<endl;
return 0;
}
*关于迭代器(iterator)
vector::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只能在容器的末尾添加新元素,只能从头部移除元素。
优先队列
priority_queue中出队顺序与插⼊顺序⽆关,与数据优先级有关,本质是一个堆
#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;//虽然进入队列的无序,但入队后自动排列,则top为最大元素
pq.pop();
}
return 0;
}
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;
}
集合(set)
集合(set)是一种包含对象的容器,可以快速地(logn)查询元素是否在已知几集合中。
set 中所有元素是有序地,且只能出现⼀次,因为 set 中元素是有序的,所以存储的元素必须已经定义 过「<」运算符(因此如果想在 set 中存放 struct 的话必须⼿动重载「<」运算符,和优先队列一样)
与set类似的还有
multiset元素有序可以出现多次
unordered_set元素无序只能出现一次
unordered_multiset元素无序可以出现多次
博客推荐:
https://www.cnblogs.com/zyxStar/p/4542835.html
映射(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;
去重函数(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( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
int main()
{
int arr[]={3,2,5,1,4};
sort(arr,arr+5);//需要先排序
cout << *lower_bound(arr,arr+5,3);//输出数组中第一个大于等于3的值
return 0;
}