STL在竞赛中的应用

STL

vector, 变长数组,倍增的思想
	size()	返回元素个数
	empty()	返回是否为空
	clear()	清空
	front()/back()
	push_back()/pop_back()
	begin()/end()
	[ ]
	支持比较运算,按字典序
系统为某一程序分配空间时,所需时间与空间大小无关,与申请次数有关,所以要尽量减少申请空间的次数,平均每插入一个数时间是O(1)的,申请空间的次数是log^n^的
	
pair<int, int>
	可以看成一个结构体,并自带比较函数
	first,第一个元素
	second,第二个元素	
	支持比较运算,以first为第一关键字,以second为第二关键字(字典序)	

sring, 字符串 
	substr()第一个参数是起始位置,第二个参数是长度
	c_str()
	size()/length()
	empty()
	clear()
	
queue, 队列
	size()
	empty()
	push()	向队尾插入一个元素
	front()	返回队头元素
	back()	返回队尾元素
	pop()	弹出队头元素
	//没有clear函数
	
priority_queue, 优先队列, 默认是大根堆
	push()
	top()
	pop()
	定义小根堆的方式:priority_pair<int, vector<int>, greater<int>> q;
	
stack, 栈
	size()
	empty()
	push()
	top()
	pop()
	
deque,双端队列
	size()
	empty()
	clear()
	front()/back()
	push_back()/pop_back()
	push_front()/pop_front()
	begin()/end()
	
set, map, multiset, multimap, 基于平衡二叉树(红黑树), 动态维护有序序列
	size()
	empty()
	clear()
	begin()/ed() 	++, -- 返回前驱和后继,时间复杂度O(log^n)
	
	set/multiset
		insert()	插入一个数
		find()	查找一个数
		count()	返回某一个数的个数
		erase()
			(1)	输入时一个数,删除所有x	O(k + log^n)
			(2) 	输入一个迭代器,删除这个迭代器
		lower_bound()/upper_bound()
			lower_bound(x)	返回大于等于x的最小的数的迭代器
			upper_bound(x)	返回大于x的最小的数的迭代器
	map/multimap
		insert()	插入的数时一个pair
		erase()		输入的参数时pair或迭代器
		[ ]	数组访问	时间复杂度时O(log^n)
		
unordered_set, unordered_map, unordered_multiset, unordered_multimap
	和上面类似,增删改查的时间复杂度时O(1)
	不支持 lower_bound()/upper_bound(), 迭代器的++, --
	
bitset, 压位
	bitset<10000> s;
	~, &, |, ^
	>>, << 
	==, !=
	[ ]
	
	count()	返回有多少个1
	
	any()	判断是否至少有一个1
	none()	判断是否全为0
	set()	把所有位置变成1
	set(k, v)	把所有为变成v
	flip() 	等价于~
	flip(k)	把第k位取反

vector的应用

vector(向量,动态数组)
1、向量的定义: vector< int > a;
2、向量的初始化:
vector < int > abc; //初始化一个size为0的vector,最常用
//初始化size,但每个元素值为默认值
vector< int > abc(10); //初始化了10个默认值为0的元素
//初始化size,并且设置初始值
vector < int > cde(10,1); //初始化了10个值为1的元素

STL中vector的基本用法
取向量首元素的迭代器: 向量名.begin();
取向量尾元素的下一个的地址: 向量名.end();
取向量首元素的值: 向量名.front();
取向量尾元素的值: 向量名.back();
下标形式访问: int value = 向量名[ 0 ]; //类似普通数组的访问
尾部添加一个元素: 向量名.push_back(value);//最常见操作
删除尾部第一个元素: 向量名.pop_back();
判断向量是否为空: 向量名.empty();
求向量元素个数: 向量名.size(); // 实际元素个数,不是容量
翻转向量: reverse( a.begin() , a.end() );

vector遍历

for (int i = 0; i < 10; i++) a.push_back(i);

for (int i = 0; i < a.size(); i++) cout << a[i] << " ";
cout << endl;

//for(auto i = a.begin(); i != a.end(); i++)
for(vector<int>::iterator i = a.begin(); i != a.end(); i++) cout << *i << " ";
cout << endl;
//a[0], a.size()

for(auto x : a) cout << x << " ";
cout << endl;

vector支持比较运算

vector<int> a(4, 3), b(3, 4);
if(a < b) cout << "a < b" << endl;//a < b

STL中vector的经典应用—邻接表

struct edge
{
int from, to, value; //定义边
}
const int maxn = 1e5 + 5 ;
vector< edge > Map[maxn]; //一维向量相当于二维数组

若用普通二维数组存邻接表,则需要1e10的空间开销,而如果途中实际变数只有1e6,则无疑会造成极大浪费(超内存)。

//初始化,clear函数是清空向量,不是变成0
//clear函数只会清除元素,但不会清除元素所占的空间

for( int i = 0; i < maxn; i++)
{
Mao[ i ].clear();
}

vector内存释放

vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
vector<int> ().swap(nums);//或者nums.swap( vector<int> () );

pair

某一个东西有两种不同的属性,可以用pair来存,需要按照某一个属性排序,排序的放到first里面
也可以存三种属性

pair<int, string> p;
pair<int, pair<int, int>> p;
	p.first
	p.second
	p = make_pair(10, "yxc");
	p = {20, "abc"};

栈的应用

栈的特点:
1、先进后出(FILO)
2、从栈顶删除元素
3、在栈顶加入元素

常见操作:
判断栈是否为空
查询栈大小
访问栈顶元素
栈顶加入元素
删除栈顶元素

queue队列

queue<int> q;
q = queue<int> ();//清空

priority_queue

默认大根堆

priority_queue<int> heap;//大根堆
priority_queue<int, vector<int>, greater<int>> heap;
heap.push(-x);

map

map<string, int> a;
	a["yxc"] = 1;
	cout << a["yxc"] << endl;

STL种栈的基本用法

创建栈对象:stack<元素类型> 栈名;
栈顶添加元素:栈名.push(元素名);
删除栈顶元素:栈名.pop();
访问栈顶元素:栈名.top();//要先确保栈非空
判断是否为空:栈名.empty();
返回栈的大小:栈名.size();

说明:栈和队列一样,没有clear之类的函数,如果想要清空一个栈,需要循环调用出栈函数

栈的实例介绍:

stack<int> s;
s.push(1);
s.push(2);
s.push(3);
s.pop();
cout << s.top() << endl;//2
s.top() += 3;
cout << s.top() << endl;//5
stack<int> s;
s.push(1);
s.push(2);
s.push(3);
cout << s.size() << endl;
while(!s.empty())
	s.pop();
cout << s.size() << endl;

例1、括号匹配问题

在这里插入图片描述
AC代码:

#include <iostream>
#include <stack>
#include <cstring>
using namespace std;

bool check(string s);

int main()
{
	string s;
	while(cin >> s)
	{
		if( check(s) )
			cout << "yes" << endl;
		else
			cout << "no" << endl;
	}
	return 0;
}

bool check(string s)
{
	stack<char> p;
	p.push('#');	//设置哨兵,防止RE
	for(int i = 0; i < s.size(); i++)
	{	
		char c = s[i];
		if(c == ')')
		{
			if( p.top != '(' )
				return false;
			else	
				p.pop();
		}
		else if( c == ']' )
		{
			if( p.top != '[' )
				return false;
			else
				p.pop();
		}
		else
			p.push(c);
	}
	return ( p.size() == 1); // 是否只剩哨兵
}	

set(集合)

数学上的集合的三个特征:
1、确定性(任一元素必须是确定属于或不属于某个集合)
2、互异性(集合中的元素互不相同)
3、无序性(集合中的元素没有先后之分)

set的含义就是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找登操作,所有的操作都是严格在logn时间内完成,效率非常高。

STL中set的基本用法

set的声明: set s;
set的清空: s.clear();
插入一个元素x:s.insert(x);//如果集合中之前没有这个元素,则成功插入并自动排序,否则不插入;
查询是否含有元素x:int hav = s.count(x); //返回0或1,因为count函数是返回出现的次数,但set函数具有互异性,只有0次或1次,所以可以判断是否出现
查找x并返回迭代器:set< int >::iterator it = s.find(x);
判断是否为空集:bool isempty = s.empty();
求集合元素个数:int n = s.size();
删除元素x:s.erase(x);
vector::erase()用于清空容器中的内容以及释放内存,并返回指向删除元素的下一个元素的迭代器。
set最主要用途:自动去重并按升序排序;
set只能通过迭代器(iterator)访问

set< int > st;
st.insert(3);	st.insert(5);
st.insert(2);	st.insert(3);
//注意,set不支持it < st.end()的写法
for(set< int >::iterator it = st.begin(); it != st.end(); it++)
{
	printf("%d ", *it);
}

对set中元素降序排列

set< int , greater < int> > st;
set< int, greater< int> >::iterator it;

结构体类型必须定义cmp函数
set< node, cmp > st;

string类

一、string对象的声明:

string str;
string str1 = "qwertyui";

二、求string对象的长度:

string str = "test";
str.length();	//结果为4
str.size();		//结果为4

三、string对象的连接
可以使用+和+=运算符对string对象执行字符串的连接操作,(还有append成员函数实现字符串连接,忽略之)

四、string对象的比较
可以用 <、<= 、==、!=、>=、>运算符直接比较string对象(还有conpare成员函数用于比较字符串。忽略之)

五、求string兑现大哥子串
substr成员函数可以用于求子串(n,m);
调用时,如果省略m或m超过了字符串的长度,则求出来的子串就是从下标n开始一直到字符串结束的部分

string s1 = "this id ok";
stirng s2 = s1.substr(2,4);	//s2 = "is i"
s2 = s1.substr(2);				//s2 = "is is ok"

cout << s1 << endl;
printf("%s\n", s1.c_str());

六、插入字符串:
insert成员函数可以再string对象中插入另一个字符串,返回值为对象自身的引用。例如:

string sl("Limitless"),s2("00");
s1.insert(2,"123");	//s1 = "Li123mitless"
s1.insert(3,s2);	//s1 = "Li10023mitless"
s1.insert(3,5,'X');	//s1 = "Li1XXXXX0023mitless"

七、删除子串:
erase成员函数可以删除string对象中的子串,返回值为对象自身的引用。
例如:

string s1("Real Steel");
s1.erase(1,3);		//s1 = "R Steel")
s1.erase(5);		//s1 = "R Ste"

八、交换两个string对象的内容
swap成员函数可以交换两个string对象的内容;(查资料swap函数属于algorithm函数库,但是我自己试验过,c++自带swap函数,可以不用写头文件或者自己定义,只能交换同类型的两个数据)

string s1("West"),s2("East");
s1.swap(s2);
//s1 = "East", s2 = "West"

九、字符串的查找操作:

string str = "The apple thinks apple is delicious";	//长度为34
stirng key = "apple";
int pos1 = str.find(key);		//4
int pos2 = str.find(key, 10);	//17

//s.find(str)	查找字符串str在当前字符串s中第一次出现的位置
//s.find(str,pos)	查找字符串str在当前字符串s的[pos,end]中第一次出现的位置

十、用STL算法操作string对象:

string s("afgcbed");
sort(s.begin(),s.end());
cout << s << endl;		//输出abcdefg
next_permutation(s.begin(),s.end());
cout << s << endl;		//输出abcdegf
reverse(s.begin(),s.end());	//翻转字符串
cout << s << endl;	//输出fgedcba

STL中的迭代器

**迭代器:**遍历容器中数据的对象。对存储与容器中的数据进行处理时,迭代器能按预先定义的顺序从一个成员移向另一个成员
也就是说,通过迭代器可以在不了解容器内部原理的情况下遍历容器。
总之,迭代器的作用就是提供一个遍历容器内部所有元素的接口,内部有一个与容器相关联的指针,然后重载各种运算操作来实现元素的遍历。

STL中的迭代器-典型用法

#include <bits/stdc++.h>
using namespace std;
int main()
{
	vector<int> vec;
	vector<int>::iterator it;
	vec.push_back(4);
	vec.push_back(2);
	vec.push_back(3);
	for(it = vev.begin(); it != vec.end(); it++)
		cout << *it << endl;
}

STL——map(映射)

map是一个键值对(key/value)容器,对于迭代器来说,可以修改value,而不能修改key。Map会根据key自动排序
map类型通常可理解为关联数组:可使用键作为下标来获取一个值。关联的本质在于:元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
特别说明:key不一定就是int类型!只要是——重载了”<“操作符的类型均可!

STL中map的基本用法

map< int, string> m;	//定义一个空map m
m.count(k);		//返回m中键值等于k的元素的个数(1或0)
m.find(k);		//存在则返回指向该元素的迭代器,否则返回结束地址end()
m.erase(k);		//删除m中键为k的元素,返回删除元素的个数(1或0)
m.erase(p);		//从m中删除迭代器p所指向的元素
m.insert(e);	//e是一个用在m上的value_type类型的值(一个pair)
//如果键e.first不在m中,则插入一个值为e.second的新元素;如果该键在m中已存在,那么不会进行任何操作
m.clear();		//清空map m;
m.empty();		//判断map m是否微空;

STL中map的元素插入和遍历1

#include <bits/stdc++.h>
using namespace std;
int main()
{
	map<int, string> mapStudent;
	mapStudent[1] = "student_one";
	mapStudent[2] = "student_two";
	mapStudent[3] = "student_three";
	map< int, string>::iterator iter;
	for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
	{
		cout << iter->first << " " << iter->second << endl;
	}
	return 0;
}
//输出
1 student_one
2 student_two
3 student_three

STL中map的元素插入和遍历2

#include <bits/stdc++.h>
using namespace std;
int main()
{
	map<string, int> mapStudent;
	mapStudent["student_one"] = 1;
	mapStudent["student_two"] = 2;
	mapStudent["student_three"] = 3;
	map<string, int>::iterator iter;
	for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
	{
		cout << iter->first << " " << iter->second << endl;
	}
	return 0;
}
//输出
student_one 1
student_two 2
student_three 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值