stl用法小结(更新中)

sort 函数:

头文件:#include

使用对象: 容器支持的迭代器类型必须为随机访问迭代器。这意味着,sort() 只对 string、array、vector、deque 这 4种容器提供支持。

写法:1.sort(arr, arr + 5) 通过下标排序2.sort(arr.begin(),arr.end()) 通过迭代器排序

排序顺序:默认按照第一个属性升序 定义compare函数可以实现其他形式排序

find函数:

头文件:#include

使用对象: 适用于所有的序列式容器。这意味着,find()对string、array、vector、deque、list、forward_list这6种容器进行支持

写法:1.使用下标确定范围 2.使用迭代器确定范围

1.char stl[] ="http://c.biancheng.net/stl/";
    //调用 find() 查找第一个字符 'c'
    char * p = find(stl, stl + strlen(stl), 'c');
    //判断是否查找成功
    if (p != stl + strlen(stl)) {
        cout << p << endl;
    }


2.vector myvector{ 10,20,30,40,50 };
  vector::iterator it;

  it = find(myvector.begin(), myvector.end(), 30);
  if (it != myvector.end())
      cout << "查找成功:" << *it;
  else
      cout << "查找失败";
  return 0;

reverse函数:

头文件:#include

使用对象和用法:1.翻转数组 reverse(a, a+n)   2翻转字符串 reverse(str.begin(), str.end())   3.翻转向量 reverse(vec.begin(), vec.end())

vector容器:

可以通过下标访问的序列式容器相当于一个长度可以改变的数组 插入取出元素从后面进后面出

 常用内置函数:

#include
vector a,b;

//b为向量,将b的0-2个元素赋值给向量a
a.assign(b.begin(),b.begin()+3);

//a含有4个值为2的元素
a.assign(4,2);

//返回a的最后一个元素
a.back();

//返回a的第一个元素
a.front();

//返回a的第i元素,当且仅当a存在
a[i];

//清空a中的元素
a.clear();

//判断a是否为空,空则返回true,非空则返回false
a.empty();

//删除a向量的最后一个元素
a.pop_back();

//删除a中第一个(从第0个算起)到第二个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)结束
a.erase(a.begin()+1,a.begin()+3);

//在a的最后一个向量后插入一个元素,其值为5
a.push_back(5);

//在a的第一个元素(从第0个算起)位置插入数值5,
a.insert(a.begin()+1,5);

//在a的第一个元素(从第0个算起)位置插入3个数,其值都为5
a.insert(a.begin()+1,3,5);

//b为数组,在a的第一个元素(从第0个元素算起)的位置插入b的第三个元素到第5个元素(不包括b+6)
a.insert(a.begin()+1,b+3,b+6);

//返回a中元素的个数
a.size();

//b为向量,将a中的元素和b中的元素整体交换
a.swap(b);

stack和queue容器:

stack是从后面插入后面取出s类似于dfs的思想 queue是从后面插入前面取出类似于bfs的思想         

stack插入:stk.push stack取出:stk.pop stack的首元素:stk.top() 

queue插入:que.push queue取出:que.pop queue的首元素:que.front() 

 set容器:

特点是不会存在有重复的元素,特殊的容器

 常用内置函数:

#include
set s;     //创建一个整型集合:s
s.insert(element);     //插入一个元素,并会自动排序(在没有自定义的情况下,缺省升序排列)
s.size();     //当前容器中元素个数
set::iterator it;//定义向前迭代器
    for(it=s.begin();it!=s.end();it++)//遍历集合中的所有元素
    {
        if(it==s.end())
         cout <<*it;
        else
         cout <<*it<<" ";
    }
查找元素位置
set::iterator pos = s1.find(30);
查找元素是否出现
int num = s1.count(30);

map容器:

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值,可以重复)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。

附:unordered_map,相比map容器里面的元素无序,占用空间,插入查询效率皆优于map

常用内置函数

#include
map map1;    //创建一个map类型,健(key)为string型,值(value)为int型。是健到值得一种映射。
map1.size()
map1.insert(pair("month",1));     //插入一个元素
map1["month"]=1;   // 插入一个元素
map1.find("month")    //查找该健,如果没有找到返回最后一位元素后面的迭代器
map1.count("month")    //查找健"month"出现的次数,但是map中健都是单一且按照升序排列的,只有0和1两中情况
map1.earse("month")  //删除month-1这一键值对
//因为map在创建的时候是有序的,所以查找效率是:logn。
map::iterator iter;  
    for(iter = map1.begin(); iter != map1.end(); iter++)  
       cout<first<<' '<second<
map::iterator iter;
	m.insert(pair("Mon",1));
	iter=m.find("Mon");
	cout<second;

pair容器:

pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,所以可以直接使用pair的成员变量。

定义:

pairp; //方式1
p.first=1;
p.second=2;


vector >vec//方式2 注意vector中放pair类型的数据时 后面的>>要分开不然会被识别">>"
vec.push_back(make_pair(1,2));

pairp(1,2); //方式3

erase函数:

erase函数的原型如下:

(1)string& erase ( size_t pos = 0, size_t n = npos );

(2)iterator erase ( iterator position );

(3)iterator erase ( iterator first, iterator last );

也就是说erase函数有三种用法:

(1)erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符

(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)

(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)

#include
using namespace std;
int main(){
	string s;
	s="abcabcdea";
	string::iterator it;
	it=s.begin();
	s.erase(it); 
	cout<<"第一种  "<

如果要删除s中所有指定的某一个特定字符如在s中删除所有字符a:

s.erase(std::remove(s.begin(), s.end(), 'a'), s.end());

lower_bound/upper_bound用法(可以用二分法实现)

前提是有序序列,lower_bound 返回第一个大于等于给定值的地址 ,upper_bound 返回第一个大于给定值的地址

求最后一个小于给定值的地址(即小于x的数里面最大的数的数的地址):lower_bound(s.begin(),s.end(),x)-1

求最后一个小于等于给定值的地址(即小于等于x的数里面最大的数的数的地址):upper_bound(s.begin(),s.end(),x)-1

#include 
#include 
#include 
using namespace std;

int main()
{
	vector v= {3,4,1,2,8};
	//先排序
	sort(v.begin(),v.end()); // 1 2 3 4 8
	
	// 定义两个迭代器变量 
	vector::iterator iter1;
	vector::iterator iter2; 
	
	iter1 = lower_bound(v.begin(),v.end(),3);//迭代器指向3
	iter2 = lower_bound(v.begin(),v.end(),7);//迭代器指向8(因为第一个大于等于8)
	
	cout << iter1 - v.begin() << endl; //下标 2
	cout << iter2 - v.begin() << endl; //下标 4 
	system("pause");
}

priority_queue 用法

定义:priority_queue
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆,定义less,重载<号,在里面实现你想要的逻辑的相反的情况 比如a>b最后返回的是小于的数排在前面
一般是:

//取队头
q.top()
//删除队头
q/pop()
//升序队列
priority_queue ,greater>q;
//降序队列
priority_queue ,less>q;
//跟pair结合 
priority_queue,vector>,greater>>q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

自定义类型重载 greater时候需要重载的类型是>,less时需要重载的类型是<  (其实用<重载时可以不写less)

#include 
#include 
using namespace std;
struct Node{
    int x, y;
    Node( int a, int b ):
        x(a), y(b) {}
	friend bool operator<(const node&a,const node&b){
		if(a.x!=b.x){
			return a.x>b.x;
		}
		else{
			return a.y b.y;
    return a.x> b.x; 
}
int main(){
    priority_queue q;
    for( int i= 0; i< 10; ++i )
    q.push( Node( rand(), rand() ) );
    while( !q.empty() ){
        cout << q.top().x << ' ' << q.top().y << endl;
        q.pop();
    }
    return 0;
}

deque成员函数用法

函数 描述
c.assign(beg,end)
c.assign(n,elem)
将[beg; end)区间中的数据赋值给c。
将n个elem的拷贝赋值给c。
c.at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range。
c.back() 传回最后一个数据,不检查这个数据是否存在。
c.begin() 传回迭代器重的可一个数据。
c.clear() 移除容器中所有数据。
deque c
deque c1(c2)
Deque c(n)
Deque c(n, elem)
Deque c(beg,end)
c.~deque()
创建一个空的deque。
复制一个deque。
创建一个deque,含有n个数据,数据均已缺省构造产生。
创建一个含有n个elem拷贝的deque。
创建一个以[beg;end)区间的deque。
销毁所有数据,释放内存。
c.empty() 判断容器是否为空。
c.end() 指向迭代器中的最后一个数据地址。
c.erase(pos)
c.erase(beg,end)
删除pos位置的数据,传回下一个数据的位置。
删除[beg,end)区间的数据,传回下一个数据的位置。
c.front() 传回地一个数据。
get_allocator 使用构造函数返回一个拷贝。
c.insert(pos,elem)
c.insert(pos,n,elem)
c.insert(pos,beg,end)
在pos位置插入一个elem拷贝,传回新数据位置。
在pos位置插入>n个elem数据。无返回值。
在pos位置插入在[beg,end)区间的数据。无返回值。
c.max_size() 返回容器中最大数据的数量。
c.pop_back() 删除最后一个数据。
c.pop_front() 删除头部数据。
c.push_back(elem) 在尾部加入一个数据。
c.push_front(elem) 在头部插入一个数据。
c.rbegin() 传回一个逆向队列的第一个数据。
c.rend() 传回一个逆向队列的最后一个数据的下一个位置。
c.resize(num) 重新指定队列的长度。
c.size() 返回容器中实际数据的个数。
C1.swap(c2)
Swap(c1,c2)
将c1和c2元素互换。
同上操作。

next_permutation和prev_permutation函数:

next_permutation以升序生成全排列,prev_permutation以降序生成全排列

#include
#include
using namespace std;
int main()
{
	int ans[4]={1,2,3,4};
	do                            
	{
		for(int i=0;i<4;++i)
			cout<

tuple元组用法

定义:pair函数只有两个成员变量first和second而tuple的成员变量数量可以自定义

 
tuple t1;            //创建一个空的tuple对象(使用默认构造),它对应的元素分别是T1和T2...Tn类型,采用值初始化。
tuple t2(v1, v2, ... TN);    //创建一个tuple对象,它的两个元素分别是T1和T2 ...Tn类型; 要获取元素的值需要通过tuple的成员get(obj)进行获取(Ith是指获取在tuple中的第几个元素,请看后面具体实例)。
tuple t3(ref&); // tuple的元素类型可以是一个引用
make_tuple(v1, v2); // 像pair一样也可以通过make_tuple进行创建一个tuple对象

//获取各个元组元素
cout << get<0>(mytuple) << " ";
cout << get<1>(mytuple) << " ";
cout << get<2>(mytuple) << " ";

multiset用法

定义:   c++语言中,multiset库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存在重复的数

#include
#define int long long
const int maxn=2e5+5;
using namespace std;
struct node{
	int x,y;
	node(int x,int y):x(x),y(y){};
};
bool operator<(const node &a,const node &b){
	if(a.x==b.x){
		return a.y>b.y;
	}
	return a.xs;
signed main(){
	s.insert(node(1,2));
	s.insert(node(1,2));
	s.insert(node(1,3));
	multiset::iterator it=s.begin();
	while(it!=s.end()){
		node now=*it;
		cout<

rope用法

rope是一种可持久化数组,采用块状链表实现,一次操作时间复杂度基本为O(\sqrt{n}),这意味着几乎所有可持久化操作都可以通过rope实现,并且因为rope还支持erase函数和insert函数,所以特别灵活,是一个可以用来解决数据结构题目的神器

引用库:需要在用的时候加上这些语句

#include 
using namespace __gnu_cxx;
ropea;

用法:最神奇的地方在于可以实现O(1)复制

#include///头文件
using namespace __gnu_cxx;
rope  x;
rope  y;
int main(){
    x.push_back(x); ///在末尾加x
    x.insert(pos, x); ///在pos位置加入x
    x.erase(pos, x); ///从pos位置删除x个元素
    x.copy(pos, len, x); ///从pos开始len个元素用x代替
    x.replace(pos, x); ///把第pos个位置换为x
    x.substr(pos, x); ///提取pos开始x个元素
    x.at(x)/[x]; ///访问第x个元素
    x.insert(x.size(),y.substr(0,y.size()));  //把y的元素添加到x的末尾
    return 0;
}

luogu3919

​

#include
#include
using namespace std;
using namespace __gnu_cxx;
const int maxn=2e6+5;
roperp[maxn];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		int now;
		cin>>now;
		rp[0].push_back(now);
	}
	for(int i=1;i<=m;i++){
		int banben,check;
		cin>>banben>>check;
		if(check==1){
			int pos,val;
			cin>>pos>>val;
			rp[banben].replace(pos-1,val);
			rp[i]=rp[banben];
		}
		else{
			int pos;
			cin>>pos;
			cout<

bitset用法

bitset其实是可以看做是一个bool类型的数组,只不过bitset的一个元素只占1bit的空间,而bool里面则是占1byte,这样就相当于同时减少了时间复杂度和空间复杂度,这也是bitset的优势所在。

bitset<10005>a;  //10005是bitset的大小,相当于数组大小,a就相当于一个bool数组。

a[0]=1;//等价于写a.set(0),令bitset的第0位为1

//快速查找x是否在集合内
if (a[x]) printf("Yes\n"); else printf("No\n");

//让x集合并上y集合
x|=y;

//让x集合交上y集合
x&=y;

//返回a集合中1的个数
a.count();

binary_search用法(要求单调递增)

在map和set中因为容器STL采用是map和set内部是红黑树实现的。因此map和set内部的find函数查找时间复杂度是O(logn),但是在vector中容器的find函数时间复杂度是O(n)的,可以用c++自带的binary_search函数查找,这个函数的要求是数组或者容器内部元素单调递增,否则会出错

#include
#include
using namespace std;
int main()
{
	vectorans;
	for(int i=0;i<26;i++){
		string tmp;
		tmp+=(char)('a'+i);
		ans.push_back(tmp);
	}
	cout<

nth_element函数

nth_element()函数将所有比第 k 个元素小的数都排在它前面,数据是无序的,
将比第 k 个元素大的数都排在它后面,数据是无序的,时间复杂度为O(n),用来求中位数模板

	for(int i=1;i<=n;i++){
		b[i]=a[i]-(i-1)*x;
	}
	nth_element(b+1,b+(n+1)/2,b+n+1);
	__int128 a0=b[(n+1)/2];

__builtin_popcount系列函数

高效位运算,时间复杂度为O(1)

//返回二进制表示中1的个数
int __builtin_popcount (unsigned int x)

//返回x的最后一位1的是从后向前第几位,比如114514(11011111101010010)返回 2。
int __builtin_ffs (unsigned int x)

//返回前导的 0 的个数。
int __builtin_clz (unsigned int x)

你可能感兴趣的:(c++)