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