C++语言(2:标准库)
.标准库
注意
标准库函数返回数值的类型大部分是size_t(unsigned long),不能直接与负数运算!
.1.标准模板库(STL)函数和算法模板
比较和比较类型less、greater和equal_to
比较必须满足严格弱序(《基础算法3.4.严格弱序》)。
在STL中,若比较函数cmp(x,y)返回true,则认为元素x比元素y小。
比较类型cmptype:
struct cmptype
{
bool operator () (const Node &x,const Node &y) const
{
return /*比较元素x,y的条件*/;
}
};
比较函数cmp:
bool cmp(Node x,Node y)
{
return /*比较元素x,y的条件*/;
}
less<type> cmp;cmp(x,y);:比较类型less<type>定义一个比较函数cmp,cmp返回命题“元素x小于元素y”的布尔值,元素需有<的定义,O(Compare)。
greater<type> cmp;cmp(x,y);:比较类型greater<type>定义一个比较函数cmp,cmp返回命题“元素x大于元素y”的布尔值,故常作为反向比较,元素需有>的定义,O(Compare)。
equal_to<type> cmp;cmp(x,y);:比较类型equal_to<type>定义一个比较函数cmp,cmp返回命题“元素x等于元素y”的布尔值,元素需有==的定义,O(Compare)。
哈希和哈希类型hash
哈希必须满足相等的对象产生相同的哈希值。
哈希类型hashtype:
struct hashtype
{
size_t operator () (const Node &x) const
{
return /*元素x的哈希值计算*/;
}
};
hash<type> hsh;hsh(x);:哈希类型hash<type>定义一个哈希函数hsh,hsh返回元素x的哈希值,元素需有哈希函数的定义,O(Calculate_Hash)。
最小值min和最大值max
根据比较函数cmp来比较大小,当cmp缺省时默认为less<type>()。
min(x,y,cmp):返回元素x和元素y的最小值,O(Compare)。
max(x,y,cmp):返回元素x和元素y的最大值,O(Compare)。
交换swap
swap(x,y):交换两个元素x,y,O(1)。
翻转reverse
reverse(bg,ed):将序列中[bg,ed)翻转,O(n)。
排序sort
底层结构:内省排序。
sort(bg,ed,cmp):将序列中[bg,ed)排序。根据比较函数cmp(注意严格弱序)来比较大小,当cmp缺省时默认为less<type>()。较小的元素排在前面。每个元素最坏参与O(log n)次比较,O((log n)*n*Compare)。
bool cmp(type x,type y)
{
return /*若返回true,则x排在y前面。注意严格弱序。*/;
}
//sort(a+l,a+r+1);//将a[l]~a[r]按从小到大排序。需有小于号的定义。
//sort(a+l,a+r+1,greater<type>());//将a[l]~a[r]按从大到小排序。需有大于号的定义。
sort(a+l,a+r+1,cmp);//将a[l]~a[r]按cmp排序。
稳定排序stable_sort
底层结构:归并排序。
与sort用法相同。稳定排序,相同元素的相对顺序保持不变。效率比sort低。
去重unique
unique(bg,ed,cmp):若比较函数cmp(x,y)返回true,则认为元素x和元素y重复,当cmp缺省时默认为equal_to<type>()。将满足重复元素相邻排列(通常配合sort使用)的序列中[bg,ed)去重,返回去重之后末尾元素的下一个位置的迭代器。去重之后末尾元素后面保留最初的序列的部分。O(n*Compare)。
第n小元素nth_element
根据比较函数cmp来排序元素和比较大小,当cmp缺省时默认为less<type>()。
nth_element(bg,nth,ed,cmp):将序列中[bg,ed)重新分配顺序,顺序位于nth的元素x分配在nth,小于或者等于x的元素分配在[bg,nth),大于或者等于x的元素分配在(nth,ed),O(n*Compare)。
nth_element(a+l,a+l+k-1,a+r+1,cmp);//将a[l]~a[r]重新分配顺序,第k小的元素分配在l+k-1,小于或者等于第k小的元素的元素分配在[l,l+k-1),大于或者等于第k小的元素的元素分配在(l+k-1,r]
二分lower_bound和upper_bound
在按照比较函数cmp(当cmp缺省时默认为less<type>())排序后的序列中:
根据cmp来比较大小,根据cmp的等价传递性来判断相等。
lower_bound(bg,ed,x,cmp):在序列中[bg,ed)二分查找最前一个大于或者等于x的元素,并且返回指向该元素的迭代器,若不存在则返回ed。
upper_bound(bg,ed,x,cmp):在序列中[bg,ed)二分查找最前一个大于x的元素,并且返回指向该元素的迭代器,若不存在则返回ed。
通过将返回的迭代器减去bg,得到找到的元素的位置。
O((log n)*Compare),需要容器支持O(1)随机访问(例如 []),否则复杂度无法保证。
上、下一个排列prev_permutation、next_permutation
next_permutation(bg,ed):整数序列中[bg,ed)是一个排列,若它已经是全排列中字典序排在最后一个的排列(元素完全从大到小排列),则将它更改为全排列中字典序排在第一个的排列(元素完全从小到大排列)并且返回false;否则,将它更改为全排列中字典序排在下一个的排列并且返回 true。O(n)。
prev_permutation(bg,ed)同理。
.2.标准模板库(STL)容器
迭代器
conttype::iterator it:声明一个访问容器类型为conttype的迭代器it,O(1)。
conttype::reverse_iterator it:声明一个访问容器类型为conttype的反向迭代器it,O(1)。
*:返回迭代器指向的元素。迭代器不可是end(),反向迭代器不可是rend()。O(1)。
->:返回迭代器指向的元素的成员。迭代器不可是end(),反向迭代器不可是rend()。O(1)。
容器
时空复杂度与当前存储元素数量n相关。
当使用删除元素类或查询元素类操作时,需要保证容器非空。
=:拷贝赋值,O(n*Copy)。
<=>:按照字典序比较两个容器,O(min(n_1,n_2)*Compare)。
map相当于set<pair<key,value>>。
无序容器仅支持==和!=,O(n*Hash*Compare),最坏O((n^2)*Compare)。
begin():返回首迭代器,O(1)。
end():返回尾迭代器,O(1)。
rbegin():返回反向首迭代器,O(1)。
rend():返回反向尾迭代器,O(1)。
empty():返回命题“是否为空”的布尔值,O(1)。
size():返回当前存储的元素的个数,O(1)。
swap(b):和容器b交换,O(1)。
彻底释放容器空间,O(n):type().swap(a)。
clear():清空,O(n)。
.2.1.向量vector
底层结构:动态数组。
支持O(1)随机访问。
声明
vector<type> a:声明一个a,O(1)。
vector<type> a(n,x):声明一个大小为n的a,并且所有元素都为x,当x缺省时默认为zero,O(n*New)。
vector<vector<type>> a(n,vector<type>(m,x)):声明一个大小为n*m的a,并且所有元素都为x,当x缺省时默认为zero,O(nm*New)。
迭代器
++、--:迭代器递增(变为指向后一个元素的迭代器)、递减(变为指向前一个元素的迭代器)。迭代器分别不可是end()、begin(),反向迭代器分别不可是rend()、rbegin()。O(1)。
+、-:迭代器是随机访问迭代器,和指针一样支持加减运算,O(1)。
迭代器失效:在容量变动后,所有迭代器可能失效。
运算符
[pos]:返回下标为pos的元素的引用,O(1)。
函数
capacity():返回实际使用内存(单位是元素个数),O(1)。
front():返回最前一个元素,O(1)。
back():返回最后一个元素,O(1)。
push_back(x):向最后插入一个元素x,O(1)。
pop_back():删除最后一个元素,O(1)。
resize(m,x):调整大小至m,调大则在新增的位置填充元素x,调小则在删减的位置删除元素,当x缺省时默认为zero,O(max(|m-n|*New,m))。
shrink_to_fit():释放多余的内存,O(n)。
注意:只有该函数才会释放内存。clear()和resize()等不会释放内存。
遍历
O(n)。
//方法一
for(type x : a) cout<<x<<" ";//type可以写为auto
//方法二
for(size_t i=0;i<a.size();i++) cout<<a[i]<<" ";
//方法三
for(vector<type>::iterator it=a.begin();it!=a.end();it++) cout<<*it<<" ";//vector<type>::iterator可以写为auto
注意
错误的写法::vector在插入元素后,所有迭代器可能失效。vector<int> a;a.push_back(6);auto it=lower_bound(a.begin(),a.end(),6);a.push_back(8);cout<<*it;
.2.2.双端队列deque
底层结构:分块数组。
支持O(1)随机访问。性能比vector差。
声明
deque<type> a:声明一个a,O(1)。
迭代器
++、--:迭代器递增(变为指向后一个元素的迭代器)、递减(变为指向前一个元素的迭代器)。迭代器分别不可是end()、begin(),反向迭代器分别不可是rend()、rbegin()。O(1)。
+、-:迭代器是随机访问迭代器,和指针一样支持加减运算,O(1)。
迭代器失效:在容量变动后,所有迭代器可能失效。
运算符
[pos]:返回下标为pos的元素的引用,O(1)。
最前一个元素的下标始终保持是0。
函数
front():返回最前一个元素,O(1)。
back():返回最后一个元素,O(1)。
push_front(x):向最前插入一个元素x,O(1)。
push_back(x):向最后插入一个元素x,O(1)。
pop_front():删除最前一个元素,O(1)。
pop_back():删除最后一个元素,O(1)。
遍历
和vector同理。
注意
deque基于分块数组,因此deque即使是空的或者只存储少量元素,也会至少占用一个完整的块的空间(e.g.512字节)。
.2.3.有序集合set和有序多重集合multiset
底层结构:红黑树。
不支持随机访问。
set元素自动去重,multiset元素可以重复。
声明
set<type,cmptype> a,multiset<type,cmptype> a:声明一个存储元素类型是type、比较类型是cmptype的a,当cmptype缺省时默认为less<type>,O(1)。
根据cmptype来排序元素和比较大小,较小的元素排在前面,根据cmptype的等价传递性来判断两个元素是否相等。
迭代器
++、--:迭代器递增(变为指向后一个元素的迭代器)、递减(变为指向前一个元素的迭代器)。迭代器分别不可是end()、begin(),反向迭代器分别不可是rend()、rbegin()。单次O(log n),当单向遍历全集时均摊O(1)。
迭代器失效:在删除元素后,只有被删除元素的迭代器失效。
函数
insert(x):插入一个元素x,并且set返回pair<iterator,bool>,first是指向插入元素或已存在元素的迭代器,second是表示插入是否成功(set若元素已存在,则不会插入重复元素);multiset返回指向插入元素的迭代器。O((log n)*Compare)。
erase(x):删除所有等于x的元素,并且返回被删除的元素数量,x可以不存在,O((log n)*Compare+Cnt)。
erase(it):删除迭代器it指向的元素,并且返回被删除元素的后继元素的迭代器,it不可以为end(),O(log n)。
multiset删除一个等于x的元素,O((log n)*Compare):
auto it=a.find(x);
if(it!=a.end()) a.erase(it);
find(x):查找最前一个等于x的元素,并且返回对应的迭代器,若不存在则返回end(),O((log n)*Compare)。
count(x):返回等于x的元素的数量,O((log n)*Compare+Cnt)。
lower_bound(x):二分查找最前一个满足大于或者等于x的元素,并且返回指向该元素的迭代器,若不存在则返回end(),O((log n)*Compare)。
upper_bound(x):二分查找最前一个满足大于x的元素,并且返回指向该元素的迭代器,若不存在则返回end(),O((log n)*Compare)。
有序插入
insert(it,x):使用提示迭代器it插入一个元素x。若提示正确(it指向的元素小于等于x并且后继元素大于等于x),则在it后插入x,当有序插入全集时均摊O(1);否则,重新查找正确位置插入x,O(log n)。并且若插入成功,则返回指向x的迭代器;否则,返回指向已存在元素的迭代器。
利用提示迭代器插入一个有序序列b的复杂度为O(n)。
set<int>::iterator it=a.begin();//set<int>::iterator可以写为auto
for(auto x : b) it=a.insert(it,x);
//multiset同理
遍历
遍历的复杂度为O(n)。
//方法一
for(type x : a) cout<<x<<" ";//type可以写为auto
//方法二
for(set<type>::iterator it=a.begin();it!=a.end();it++) cout<<*it<<" ";//set<type>::iterator可以写为auto
//multiset同理
注意
错误的写法::因为不支持随机访问,所以这种写法的时间复杂度为O(n)。auto it=lower_bound(s.begin(),s.end(),x);
.2.4.有序映射map
底层结构:红黑树。
map相当于set<pair<type1,type2>>,因此下文只写map的优势部分。
声明
map<type1,type2,cmptype> a;:声明一个存储键元素类型是type1、值元素类型是type2、针对type1的比较类型是cmptype的a,当cmptype缺省时默认为less<type>,O(1)。
根据cmptype来排序元素,根据cmptype的等价传递性来判断两个键元素是否相等。
运算符
[x]:查找等于x的键,并且返回x映射到的值y的引用,若不存在则先自动插入映射元素{x,y=zero}再返回y的引用,O((log n)*Compare)。
可以在使用[x]之前使用find()检查x的存在性,以避免自动插入过多的{x,zero}。
函数
erase(x):删除等于x的键和对应的映射元素,并且返回被删除的映射元素数量,x可以不存在,O((log n)*Compare)。
find(x):查找等于x的键,并且返回指向对应的映射元素的迭代器,若不存在则返回end(),O((log n)*Compare)。
.2.5.无序映射unordered_map
底层结构:哈希表。
声明
unordered_map<type1,type2,hashtype,cmptype> a;:声明一个存储键元素类型是type1、值元素类型是type2、针对键元素的哈希类型是hashtype、针对键元素的比较类型cmptype的a,当hashtype、cmptype缺省时分别默认为hash<type>、equal_to<type>,O(1)。
若hash(x)等于hash(y)并且cmp(x,y)返回true,则认为两个键元素x,y相等。
运算符
[x]:查找等于x的键,并且返回x映射到的值y的引用,若不存在则先自动插入映射元素{x,y=zero}再返回y的引用,O(Hash*Compare),最坏O(n*Compare)。
可以在使用[x]之前使用find()检查x的存在性,以避免自动插入过多的{x,zero}。
函数
erase(x):删除等于x的键和对应的映射元素,并且返回被删除的映射元素数量,x可以不存在,O(Hash*Compare),最坏O(n*Compare)。
find(x):查找等于x的键,并且返回指向对应的映射元素的迭代器,若不存在则返回end(),O(Hash*Compare),最坏O(n*Compare)。
.3.标准模板库(STL)容器适配器
时空复杂度与当前存储元素数量n相关。
不支持随机访问和迭代器。
当使用删除元素类或查询元素类操作时,需要保证容器非空。
=:拷贝赋值,O(n*Copy)。
empty():返回命题“是否为空”的布尔值,O(1)。
size():返回当前存储元素个数,O(1)。
swap(b):和容器b交换,O(1)。
彻底释放容器空间,O(n):type().swap(a)。
.3.1.栈stack和队列queue
底层结构:基于底层容器(默认deque)。
声明
stack<type,conttype> a、queue<type,conttype> a:声明一个存储元素类型是type、底层容器类型是conttype的a,当conttype缺省时默认为deque<type>,O(1)。
运算符
<=>:按照字典序比较两个容器,O(min(n_1,n_2)*Compare)。
函数
push(x):向最后插入一个元素x,O(1)。
pop():
stack:删除最后一个元素,O(1)。
queue:删除最前一个元素,O(1)。
top():stack:返回最后一个元素,O(1)。
front():queue:返回最前一个元素,O(1)。
back():queue:返回最后一个元素,O(1)。
注意
stack和queue默认基于deque,因此也会有deque的空间注意事项,可以令conttype为list<type>来解决。
.3.2.优先队列priority_queue
底层结构:基于底层容器(默认vector),并使用大根堆算法。
声明
priority_queue<type,conttype,cmptype> a:声明一个存储元素类型是type、底层容器类型是conttype、比较类型是cmptype的a,当conttype缺省时默认为vector<type>,当cmptype缺省时默认为less<type>,O(1)。
根据cmptype来排序元素和比较大小,最大的元素排在堆顶top()。
函数
push(x):插入一个元素x,O(log n*Compare)。
pop():删除一个最大的元素,O(log n*Compare)。
top():返回最大的元素,O(1)。
技巧
-
懒惰删除法
priority_queue不支持随机删除操作。当遇到删除操作时,可以使用其他的数据结构维护一些信息(e.g.数组记录元素的最新值),用于后面在使用最大的元素时检查是否已被删除。 -
结构体小于号的定义:
struct Node
{
bool operator < (const Node & that) const
{
return ;//返回false的排在堆顶top
}
};
priority_queue<Node> q;
.4.其他常用内容
.4.1.字符串string
底层结构:类似vector<char>。
支持O(1)随机访问。
时空复杂度与当前字符串长度n相关。
string相当于vector<char>,因此下文只写string的优势部分。
声明
string a:声明一个a,O(1)。
读入和输出
cin、cout:和字符数组一样。cin读入空白字符停止。
getline(cin,a):整行读入至字符串a。
运算符
[pos]:返回下标为pos的字符的引用,O(1)。
=:拷贝赋值,O(n)。
<=>:按照字典序比较两个字符串,O(min(n_1,n_2))。
对n个字符串执行sort,这个n个字符串的总长度是m,复杂度是O((log n)*m)。
+:返回两个字符串的拼接字符串,O(n_1+n_2)。
+=:在本字符串后拼接(长度为m的)字符串,O(m)。
函数
size()、length():返回当前字符串长度,O(1)。
c_str():返回C风格字符串const char*,O(1)。
find(str,pos):查找并返回从下标pos开始(含pos)最前出现(长度为m的)字符串str的首字符下标,若不存在则返回string::npos(被定义为-1的size_t),当pos缺省时默认为0,O(nm)。
substr(pos,len):返回从下标pos开始(含pos)截取长度为len的字符串,若从pos开始的后缀的长度小于len则返回这个后缀,当len缺省时返回从pos开始的后缀,O(len)。
swap(b):和字符串b交换,O(1)。
彻底释放字符串空间,O(n):string().swap(a)。
遍历
O(n)。
//方法一
for(char x : a) cout<<x<<" ";//char可以写为auto
//方法二
for(size_t i=0;i<a.size();i++) cout<<a[i]<<" ";
//方法三
for(string::iterator it=a.begin();it!=a.end();it++) cout<<*it<<" ";//string::iterator可以写为auto
.4.2.位集合bitset
底层结构:固定大小的位数组。
支持O(1)随机访问。
时空复杂度与声明的位集合大小N相关。
声明
bitset<N> a:声明一个大小为N的a,初值是false,O(N/w)。
运算符
[pos]:返回第pos位的引用,O(1)。
&、&=、|、|=、^、^=、~、<<、<<=、>>、>>=:N位二进制数的位运算,O(N/w)。
=:拷贝赋值,O(N/w)。
==、!=:判断两个大小为N的位集合是否相等、不相等,O(N/w)。
函数
size():返回位集合的大小,O(1)。
count():返回值为true的位的个数,O(N/w)。
all():返回命题“所有位为true”的布尔值,O(N/w)。
any():返回命题“至少有一位为true”的布尔值,O(N/w)。
none():返回命题“所有位为false”的布尔值,O(N/w)。
set():把所有位设置为true,O(N/w)。
reset():把所有位设置为false,O(N/w)。
flip():把所有位取反,O(N/w)。
遍历
_Find_first():查找并返回最前的值为true的位的下标,O(len/w),其中len是该位的下标。
_Find_next(pos):查找并返回在第pos位之后(不含pos)最前的值为true的位的下标,O(len/w),其中len是该位和pos的距离。
遍历所有值为true的位的下标的复杂度是O(N/w+m),其中m是值为true的位的个数。
for(size_t i=a._Find_first();i<a.size();i=a._Find_next(i))
.4.3.随机
-
random_device srd;srd();:随机数生成器类型random_device定义一个随机数生成器srd,随机数函数srd()返回一个在unsigned int的范围([0,2^32-1])内的随机数,O(1)。真随机数,来源于操作系统的熵池。但性能慢,故用于生成随机种子而非随机数。
random_device srd;
unsigned int r=srd();
-
mt19937_64 gen(seed);gen();:随机数生成器类型mt19937_64定义一个随机种子为seed的随机数生成器gen,随机数函数gen()返回一个使用seed生成的在unsigned long long的范围([0,2^64-1])内的随机数,当seed缺省时默认为默认随机种子,O(1)。伪随机数。注意要先随机种子,可以利用真随机数
(random_device()())来随机种子。
mt19937_64 gen((random_device()()));//注意要先随机种子
unsigned long long r=gen();
-
mt19937 gen(seed);gen();:随机数生成器类型mt19937定义一个随机种子为seed的随机数生成器gen,随机数函数gen()返回一个使用seed生成的在unsigned int的范围([0,2^32-1])内的随机数,当seed缺省时默认为默认随机种子,O(1)。其他地方与
mt19937_64相同。 -
uniform_int_distribution<type> dist(l,r);dist(gen);:随机数分布类型uniform_int_distribution<type>定义一个随机数类型为type、范围为[l,r]的随机数均匀分布函数dist,dist返回一个利用随机数生成器(e.g.mt19937_64())gen和均匀分布来生成的在[l,r]内的随机整数。不可l>r。当l、r缺省时分别默认为0、type的最大值numeric_limits<type>::max()。O(1)。 -
uniform_real_distribution<type> dist(l,r);dist(gen);:随机数分布类型uniform_real_distribution<type>定义一个随机数类型为type、范围为[l,r)的随机数均匀分布函数dist,dist返回一个利用随机数生成器(e.g.mt19937_64())gen和均匀分布来生成的在[l,r)内的随机实数。当l>r时自动交换边界。当l、r缺省时分别默认为0.0、1.0。O(1)。
随机整数[l,r]
mt19937_64 gen((random_device()()));
type rnd(type l,type r)
{
uniform_int_distribution<type> dist(l,r);
return dist(gen);
}
随机实数
- [l,r)
mt19937_64 gen((random_device()()));
type rnd(type l,type r)
{
uniform_real_distribution<type> dist(l,r);
return dist(gen);
}
- [l,r]
mt19937_64 gen((random_device()()));
type rnd(type l,type r)
{
uniform_real_distribution<type> dist(l,nextafter(r,numeric_limits<type>::max()));
return dist(gen);
}
随机排列shuffle
shuffle(bg,ed,gen):利用随机数生成器(e.g.mt19937_64())gen来打乱序列中[bg,ed)的顺序,当缺省gen时默认为默认随机种子。O(n)。

浙公网安备 33010602011771号