C++ STL 算法竞赛常用模板归纳汇总

向量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()返回的是一个无意义的值,它是最后一个元素迭代器之后的一个迭代器 
	
} 

 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值