C++语言(2:标准库)

.标准库

注意

标准库函数返回数值的类型大部分是size_tunsigned long),不能直接与负数运算!

.1.标准模板库(STL)函数和算法模板

比较和比较类型lessgreaterequal_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_boundupper_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_permutationnext_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<int> a;a.push_back(6);auto it=lower_bound(a.begin(),a.end(),6);a.push_back(8);cout<<*it;:vector在插入元素后,所有迭代器可能失效。

.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> amultiset<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同理

注意

错误的写法:auto it=lower_bound(s.begin(),s.end(),x);:因为不支持随机访问,所以这种写法的时间复杂度为O(n)。

.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> aqueue<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)。

注意

stackqueue默认基于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)。

技巧

  1. 懒惰删除法

    priority_queue不支持随机删除操作。当遇到删除操作时,可以使用其他的数据结构维护一些信息(e.g.数组记录元素的最新值),用于后面在使用最大的元素时检查是否已被删除。

  2. 结构体小于号的定义:

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)。

读入和输出

cincout:和字符数组一样。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(被定义为-1size_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.01.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)。

posted @ 2025-09-29 17:08  Brilliance_Z  阅读(233)  评论(0)    收藏  举报