向量vector(相当于可变长数组)
/*STL库
vector、deque、list、set、
map、multiset、multimap、unordered_set、
unordered_map、unordered_multiset、unordered_multimap、
stack、queue、priority_queue、string、pair*/
#include <vector>
#include <bits/stdc++.h>
using namespace std;
int main(){
//vector
//定义:vector<数据类型> 名称 (元素个数,[初值])
vector<int> vec; //创建一个长度为 0的初始数组
vector<int> vec2(100,1); //创建一个元素个数为100,初值为1的初始数组
//创建一个名为arr2的二维数组,这个数组有5行,4列,初值为 1
//相当于[ [1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,1,1] ]
vector< vector<int> > arr( 5, vector<int> (4,1) ) ;
//创建一个名为arr3的三维数组,这个数组为5*6*4,初值是0
vector< vector< vector<int> > > arr3( 5 , vector< vector<int> > ( 6,vector<int>(4,0) ) );
//为vector数组 vec增加元素7,13(在末尾加上)
vec.push_back(7); //在末尾放上7
vec.push_back(13); //在末尾放上13
//删除vector数组的元素7(删除末尾的)
vec.pop_back();
//快速清空vector数组
vec.clear();
//判断数组vec是否为空
vec.empty(); //它返回的是一个布尔型变量
//重新设置数组vec大小,将其设为5,补充的初值为3,则vec变为[7,3,3,3,3],如果不设置初值,新增空间默认补 0
vec.resize(5,3) ;
vec.resize(3); //如果新设置的大小比原来的小,那么会把原数组最后的几个元素删除,vec变为[7,3,3]
//获取此时vector数组的大小
vec.size();
return 0;
}
PS:vector数组的动态长度机制是这样的,加入我首先开了一个长度为10的vector数组,当这个数组存储的元素数目大于10的时候,vector会自动开一个大小为当前vector大小的2倍的新数组vector2,并将vector的数据全部复制到vector2中去(如果再超出限度就再开一个大小是vector2的2倍的新数组vector3,以此类推……)
stack:栈
/*STL库
vector、deque、list、set、
map、multiset、multimap、unordered_set、
unordered_map、unordered_multiset、unordered_multimap、
stack、queue、priority_queue、string、pair*/
#include <stack>
#include <bits/stdc++.h>
using namespace std;
int main(){
//stack:栈,先进后出
//定义:stack<数据类型> 名称
stack<double> stk;
//进栈:
stk.push(1.2);
stk.push(1.5);
stk.push(3.3);
//出栈 :
stk.pop() ;
//查看栈顶元素
stk.top() ;
//查看栈的元素个数
stk.size();
//判断栈是否为空
stk.empty();
// 注:vector也可以当栈使用
vector<double> vec;
//进栈:
vec.push_back(1.2);
vec.push_back(1.5);
vec.push_back(3.3);
//出栈:
vec.pop_back()
return 0;
}
Pair元组
#include<bits/stdc++.h>
using namespace std;
int main(){
pair<int,int> p ={1,2}; //定义二元组
pair<pair<int,char>,int> m ;//定义三元组
//cout<<p.first<<" "<<p.second<<endl;
vector< pair<int,int> > vec={{1,2},{3,4},{5,6}};
for(int x=0;x<vec.size();x++){
//ps:pair不能直接输出,只能分别输出其第一个元素与第二个元素
cout<<vec[x].first<<","<<vec[x].second<<endl;
}
}
queue,priority_queue:队列与优先队列(本质是堆)
#include<queue>
#include<priority_queue>
#include<iostream>
using namespace std;
int main(){
//queue:队列
queue<int> zhang; //声明队列
//进队:
zhang.push(1);
zhang.push(2);
zhang.push(3);
//查看队首,队尾:
zhang.front() ;
zhang.back();
//出队:
zhang.pop();
zhang.pop();
//查看队列大小:
zhang.size();
//判空:
zhang.empty();
//priority_queue:优先队列(本质是堆)
priority_queue<int> zhangyu; //默认是一个大顶堆
//进堆
zhangyu.push(1);
zhangyu.push(3);
zhangyu.push(10);
zhangyu.push(7);
//查看堆顶(大顶堆的堆顶元素是整个堆的最大值)
zhangyu.top();
//出堆(把堆顶元素弹出)
zhangyu1.pop();
//创建一个小顶堆,第一个参数是堆的数据类型,第二个参数是堆的底层存储结构(默认是vector) ,第三个参数是一个反函数
priority_queue< double, vector<double> ,greater<double> > sen;
sen.push(1);
sen.push(3);
sen.push(5);
sen.push(9);
sen.top(); //结果会是1,小顶堆的堆顶元素是整个堆中最小的值
//修改堆顶元素 ,将堆顶元素+1
int x=sen.top();
sen.pop();
sen.push(x+1) ;
}
deque:双端队列(速度较慢,竞赛中慎用)
#include<bits/stdc++.h>
using namespace std;
int main(){
deque<int> de={1,3,7,5,9}; //deque双端队列
de.size();//查看队列的元素个数
de.empty();//判空
de.clear();//清空
de.front();//查看队列的第一个元素
de.back();//查看队列的最后一个元素
de.push_back(334);//从队尾插入元素
de.push_back(1231);
de.push_front(7979);//从队首插入元素
de.push_front(9999);
for (auto x:de){
cout<<x<<endl;
}
}
string:字符串
#include<bits/stdc++.h>
using namespace std;
int main(){
string yusen;
cin>>yusen;//输入字符串
cout<<yusen;//输出字符串
/*使用scanf与printf输入输出字符串(不建议用)
string ss;
char huanchong[100];
scanf("%s",&buf);
ss=buf;
printf("%s",ss.c_str());
注:"%s"只认字符数组 c_str()将ss转换为字符数组 */
//构造由100个a组成的字符数组,注意是'a'不是"a" ,"a"是字符串,'a'是字符
string s(100,'a');
cout<<s<<endl;
string s1="123";
string s2="778";
//比对字符串
if(s1==s2){
printf("yes");
}
//相加、取子串
string s3=s1+s2;
//第一个参数是子串的起始下标
//第二个参数是子串的长度 ,第二个参数的定义与其它语言不同
cout<<s3.substr(3,2)<<"\n"<<endl;
//找子串
cout<<s3.find("7789")<<"\n"<<endl;
//如果在s3中找到了这个子串,find()会返回这个子串的起始下标
//没找到,就会返回一串失败数 ,失败数是 string::npos
//数值转字符串
int x=368900832;
s=to_string(x);//注意,这里的数值精度是有限的,太大的数或高精度的数据转换不了
cout<<s<<endl;
//提速
string ssr;
ssr=ssr+"a";//慢速,因为缓存中会再开一个ssr,再把ssr+a拷贝过去
ssr+=a; //快速,只需要在原ssr空间再尾接一个a即可
}
map:映射(类似于字典)
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
//映射map:类似于python中的字典
//构建一个键是string类型,值是int类型的映射a
map<string,int> a; //map<键的类型,值的类型> 名称;
//map的键只能出现一次,并且它的"键是按照升序排序"的
int main(){
map<int,int> mp;
mp[2];//当访问mp中的一个不存在的元素时,mp会自动为 mp[2]赋上一个初值0
mp[2]=5;//存储元素
mp.erase(2);//删除键为2的元素
//使用find函数查找map中的键 ,find如果查到,就会返回这个键的迭代器,查不到就返回尾迭代器
if(mp.find(2)!=mp.end()) {
printf("yes");
}
//判断键是否存在
mp.count(2); //查找键为2的元素个数
mp.clear();//清空map
mp.empty();///判空
mp[3]=2;
mp[6]=6;
mp[1]=9;
mp[13]=901;
//迭代器遍历map,first是键值对的键,second是键值对的值
for(auto &i:mp){
cout<<i.first<<" "<<i.second<<endl;
}
for (map<int,int>::itrator it=mp.begin(); it!=mp.end() ;it++){
cout<<it->first<<' '<<it->second<<endl;
}
}
set:集合
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
/*
要素 set multiset unordered_set
互异性 是 否(一个元素可出现任意次) 是
无序性 否(元素被从小到大排序) 否(从小到大) 是
应用:
1.因为集合set满足互异性,所以可以用它来去重
2.因为集合set可以把内部元素排序,所以可以用它来排序
*/
int main(){
set <int> zhang; //声明集合
// 清空集合
zhang.clear();
//插入元素
zhang.insert(3);
zhang.insert(4);
zhang.insert(17);
zhang.insert(12);
//删除元素 17
zhang.erase(17) ;
//查找元素
/*count这个函数会返回元素 12在集合中的出现次数 ,因为set集合是元素互异的
所以如果12存在就会返回 0,否则返回 1 */
zhang.count(12) ;
//查看集合大小
zhang.size();
// 集合判空
zhang.empty();
//迭代器
/*
下面的代码首先声明了一个名为 yusen的set类型迭代器,它的初值是zhang.begin(),
这个是zhang的初始位置迭代器,如果yusen没有走到zhang.end(),
也就是末尾迭代器,yusen就自加 1,迭代器的本质是一个对象,初学者可以理解为地址
*/
for(set<int>::iterator yusen=zhang.begin(); yusen!=zhang.end(); yusen++){
cout<<*yusen<<endl;
}
//打印输出
for(auto &i:zhang){ //auto是一个自动类型的变量,它可以自动推导出变量的类型
cout<<i<<endl;
}
return 0;
}
迭代器与常用便捷算法
//STL便捷算法
#include<bits/stdc++.h>
using namespace std;
//需要用到哪个就把哪部分注释取消即可
int main(){
/*
//swap交换函数
string a="zhang",b="yusen";
cout<<a<<" "<<b<<endl;
swap(a,b);
cout<<a<<" "<<b<<endl;
*/
/*
//sort排序函数
vector<int> zhang={1,3,2,1,32} ;
//默认升序排序
sort(zhang.begin(),zhang.end());
for(vector<int>::iterator yu=zhang.begin(); yu!=zhang.end(); yu++){
cout<<*yu<<endl;
}
//降序排序
sort(zhang.begin(),zhang.end(),greater<int>());
for(vector<int>::iterator yu=zhang.begin(); yu!=zhang.end(); yu++){
cout<<*yu<<endl;
}
//数组排序
int sa[]={1,6,3,8,90,8,7,4};
sort( begin(sa) , end(sa) ,greater<int>());//数组降序排序
for(int i=0;i<8;i++){
printf("%d ",sa[i]);
}
*/
/*
//二分查找:现有升序数组[1,1,2,3,3,6,6,7,7,8,29]
//lower_bound():寻找升序序列中大于等于x的第一个元素的位置
//upper_bound():寻找升序序列中大于x的第一个元素的位置
vector<int> arr={0,1,1,8,9,9};
int pos=lower_bound(arr.begin(),arr.end(),8) - arr.begin();
//lower_bound()返回的是元素8位置的迭代器, 减去arr.begin(),可以得到8在数组中的下标
*/
/*
//反转序列
printf("\n\n\n") ;
vector<int> arr2={0,1,2,3,4,5,6,7,8,9};
reverse(arr2.begin(),arr2.end());//将序列全部反转
//reverse(1,4);//将序列下标为1-3的子序列反转,左闭右开的区间
//arr.begin()是指向序列第0个元素的迭代器
//arr.end()是指向序列末尾元素的下一个元素的迭代器
for(auto i:arr2){
cout<<i<<endl;
}
*/
/*
//最大值,最小值
int a=3;
int b=5;
int c=66;
cout<<max( max(a,b) ,c )<<endl;
cout<<min( min(a,b) ,c )<<endl;
*/
/*
//数组去重:unique
vector <int> arr={1,2,1,4,5,4,4};
//unique只能对有顺序的数组去重,所以要先排序
sort(arr.begin(),arr.end());
//此时arr={1,1,2,4,4,4,5}
auto l=unique(arr.begin(),arr.end()) ;
//此时arr={1,2,4,5,*,*,*} unique会返回第一个*的迭代器,*表示混乱但存在的数据
arr.erase( l , arr.end() ); //把m到arr.end()之间的所有元素全部清除
for(auto ele:arr){
cout<<ele<<" ";
}
*/
/*
最大公因数(Greatest Common Divisor)
最小公倍数(Least Common Multiple):
GCD*LCM=a*b;
求a,b的最大公因数:int gcd=__gcd(a,b)
求a,b的最小公倍数:int lcm=a*b/gcd
auto g =__gcd(8,12);
auto l=8*12/g;
cout<<g<<" "<<l<<endl;
*/
/*
//以2为底的对数
auto s=log2(9);
//以e为底的对数
auto q=log(18);
//绝对值
auto r=abs(-3.14);
//指数e的5次方
auto t=exp(5);
//乘方 2**3
auto u=pow(2,3);
//四舍五入
auto v=round(3.5);
//向上取整
auto w=ceil(22.3);
cout<<s<<" "<<q<<" "<<r<<" "<<t<<" "<<u<<" "<<v<<" "<<w;
*/
}
//迭代器:用来遍历无法用下标来表示元素的数据结构 ,比如树,图
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int main(){
set<int> yusen;
yusen.insert(5);
yusen.insert(3);
yusen.insert(89);
for(set<int>::iterator zhang=yusen.begin(); zhang!=yusen.end(); zhang++){
cout<<*zhang<<" "<<endl; //一定要记得加星号 ,*是根据地址取值
}
//迭代器-迭代器可以得到两个迭代器之间的距离(整形)
//迭代器的end()返回的是一个无意义的值,它是最后一个元素迭代器之后的一个迭代器
}