Aotle

你所看到的惊鸿,都曾被平庸磨练

STL函数总结,用到不熟悉的再总结吧

algorithm

lower_bound():

头文件: #include<algorithm>

函数模板: 如 binary_search()

函数功能: 函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置

举例如下:

一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标

pos = lower_bound( number, number + 8, 3) -number,pos = 0.numbe数组的下标为0的位置。

pos = lower_bound( number, number + 8, 9) -number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。

pos = lower_bound( number, number + 8, 111)- number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。

所以,要记住:函数lower_bound()firstlast中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~

返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置

upper_bound():

头文件:#include<algorithm>

函数模板: 如binary_search()

函数功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置

例如:一个数组number序列1,2,2,4.upper_bound(2)后,返回的位置是3(下标)也就是4所在的位置,同样,如果插入元素大于数组中全部元素,返回的是last。(注意:数组下标越界)

返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置

注意:

lower_bound(val):返回容器中第一个值【大于或等于】val的元素的iterator位置。

upper_bound(val): 返回容器中第一个值【大于】val的元素的iterator位置。

lower的意义是对于给定的已经排好序的a,key最能插入到那个位置

0 1 | 2 2 3 所以2最插入到2号位置

upper的意义是对于给定的已经排好序的a,key最能插入到那个位置

0 1 2 2 | 3 所以2最插入到4号位置

查找某个元素是否出现(二分法查找)binary_search(a,a+n,number)

fill():

和sort差不多,fill(a,a+n,number)给数组||容器赋值number

max_element() & min_element():

这个的话还是蛮好用的,比自己一个循环写下来要快的多了,简单用法如下:

1
position=max_element(a,a+n)-a;

这样写的话就代表的是找到的最大元素的位置在哪里,position代表位置, 值得注意的一点是这个返回的是最大元素的位置,即指针指向第一个最大元素我们用以下方式表示找到的最大元素的值

1
printf("%d\n",*max_element(a,a+n));

同时 min_element的用法同上,但是都有一个共同点,就是找到的位置都是第一个最大(小)的元素,即存在多个相同大小的元素的时候找到的是第一个.

min(),max()

最大最小

swap()

swap(a,b)交换

reverse()

反转reverse(v.begin(), v.end()); reverse(a,a+n)

sort(),stable_sort()

sort(v1.begin(), v1.end(), cmp); //不稳定排序
stable_sort(v1.begin(), v1.end(), cmp); //稳定排序

find()

find函数主要实现的是在容器内(数组也可以)查找指定的元素,并且这个元素必须是基本数据类型的。
查找成功返回一个指向指定元素的迭代器,查找失败返回end迭代器。

还有一个find_if()函数。

iter = search(v1.begin(), v1.end(), v2.begin(), v2.end()); //在v1中查找是否有区间包含v2,若没找到,返回v1.end()

用于在序列 A 中查找序列 B 第一次出现的位置。

迭代器

1
2
3
4
5
6
7
8
9
10
11
begin() / end();    //迭代
rbegin() / rend(); //反向迭代
cbegin() / cend(); //const迭代
crbegin() / crend(); //const反向迭代

//冒号遍历,基于迭代器实现,但遍历过程中insert和erase将引发无定义的行为,
//不能修改set和map的key等本身无法修改的元素
for (auto v:vec); //冒号遍历(只读)
for (auto& v:vec); //冒号遍历(读写)

iter = set1.erase(iter); //迭代过程中的安全erase

string

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>

string s1("hello"); //与下一行效果相同
string s1 = "hello";
string s1(4, '='); //生成4个'='组成的字符串
string s1(s2, 0, s2.size()); //拷贝另一个字符串的某个区间初始化

s1.clear(); //清空
s1.size(); //返回字符串长度,与下一行效果相同(不计'\0')
s1.length();
s1.empty(); //是否为空

s1.c_str(); //返回const char*形式
s1.substr(0, s1.size()); //返回指定区间内的子串,深拷贝
s1.append(s2, 0, s2.size()); //字符串后接另一个字符串的某个区间

to_string(100); //数值型转字符串
stoi("100"); //字符串转整型
stod("0.1"); //字符串转浮点型

vector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <vector>

vector<int> v1 = v2; //深拷贝构造
vector<int> v1 = {0,1,2,3}; //initializer_list初始化
vector<int> v1(v2.begin(), v2.end()); //vector或array初始化
vector<int> v1(7); //初始化有7个元素的vector
vector<int> v1(7, 3) //初始化有7个3的vector
vector<int> v1(r, vector<int>(c, 0)) //初始化r行c列全为0的矩阵

v1.clear(); //清空
v1.size(); //返回元素数量
v1.empty(); //是否为空

v1.front(); //访问第一个元素
v1.back(); //访问最后一个元素

v1.push_back(100); //末尾插入元素
v1.pop_back(); //清除末尾元素

iter = v1.insert(v1.begin(), 100); //在vector最前面插入100
iter = v1.insert(v1.begin(), v2.begin(), v2.end()); //插入另一个数组
iter = v1.erase(v1.begin()+2); //erase一个数
iter = v1.erase(v1.begin()+2, v1.begin()+5); //erase一个区间

stack

1
2
3
4
5
6
7
8
9
10
#include <stack>

s1.clear(); //清空
s1.size(); //返回元素数量
s1.empty(); //是否为空

s1.top(); //返回栈顶元素

s1.push(100); //压栈
s1.pop(); //弹栈

queue/deque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <queue>
#include <deque>

q1.clear(); //清空
q1.size(); //返回元素数量
q1.empty(); //是否为空

q1.front(); //返回第一个元素
q1.back(); //返回最后一个元素

q1.push_front(100); //首位插入100
q1.push_back(100); //末位插入100
q1.pop_front(); //弹出第一个元素
q1.pop_back(); //弹出最后一个元素

优先级队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//使用堆实现,建堆O(n),插入O(logn),删除O(logn),查找同vector
#include <queue>

priority_queue<int, vector<int>, less<int>> maxQ; //大顶堆
priority_queue<int, vector<int>, greater<int>> minQ; //小顶堆
priority_queue<int> q1(less<int>(), v1); //用v1初始化大顶堆

q1.clear(); //清空
q1.size(); //返回元素数量
q1.empty(); //是否为空

q1.top(); //返回堆顶元素

q1.push(100); //压入堆
q1.pop(); //弹出堆顶

//自定义比较函数Comp类的写法
struct CompLess {
bool operator() (const int a, const int b) {
return a < b;
}
};

//另一种建heap的方式
#include <algorithm>
std::make_heap(v.begin(), v.end(), comp); //建最大堆,v.front()为最大元素

v.push_back(6);
std::push_heap(v.begin(), v.end()); //其他部分为最大堆,末尾元素为新插入,进行上滤

std::pop_heap(v.begin(), v.end(), comp); //堆顶与堆底交换,然后下滤
v.pop_back()

pair

1
2
3
4
5
6
7
#include <utility>
pair<int, string> p1(1, "Tom"); //生成一个pair
pair<int, string>(1, "Tom"); //与下两行效果相同,类型由用户指定
pair(1, "Tom"); //与上一行效果相同,编译器判断变量类型
make_pair(1, "Tom"); //与上一行效果相同,编译器判断变量类型
p1.first;
p1.second;

set/multiset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//基于红黑树实现,有自动排序,插入O(logn),查找O(logn),删除O(logn)
//也导致无法直接修改set中的元素,只能先删除再插入
#include <set>
#include <multiset>

set<int, less<int>> c1(c2); //深拷贝构造
set<int, less<int>> c1(c2.begin(), c2.end());
set<int, less<int>> c1(c2.begin(), c2.end(), comp); //迭代器返回的元素依次排序

c1.clear(); //清空
c1.size(); //返回元素数量
c1.empty(); //是否为空

c1.count(elem); //返回elem的count,可以用于判断set中是否有elem
c1.find(elem); //返回指向elem的迭代器,用"!=c1.end()"判断是否找到
c1.lower_bound(elem); //返回指向首个不小于elem的迭代器
c1.upper_bound(elem); //返回指向首个大于elem的迭代器

c1.insert(elem); //插入单个elem
c1.insert(c2.begin(), c2.end()); //插入另一个set的某个区间
c1.erase(elem); //返回被移除的元素的数量
c1.erase(iter); //清除iter指向的元素
c1.erase(c1.begin()+2, c1.begin()+5); //清除某个区间

unordered_set/unordered_multiset

1
2
3
4
5
6
//基于哈希表实现,插入O(n),查找O(n),删除O(n)
//代价占用内存比set/multiset略大一点点,内部元素不排序
#include <unordered_set>

//大部分函数同set/multiset
//由于内部元素不排序,不能使用lower_bound和upper_bound

map/multimap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//基于红黑树实现,依据key自动排序,插入O(logn),查找O(logn),删除O(logn)
//也导致无法直接修改map中的元素,只能先删除再插入
#include <map>

map<int, string> m1 = {{2015, "Tom"}, {2016, "Jim"}}; //构造函数

m1.clear(); //清空
m1.size(); //返回元素数量
m1.empty(); //是否为空

m1.at[2015] = "Tom"; //取值,会检查key是否存在
m1[2015] = "Tom"; //若key存在则修改value,若不存在则创建

m1.count(key); //返回相应key的count,可以用于判断map中是否存在该key
iter = m1.find(key); //返回指向key的迭代器,用"!=m1.end()"判断是否找到
c1.lower_bound(key); //返回指向首个不小于key的迭代器
c1.upper_bound(key); //返回指向首个大于key的迭代器

m1.insert(make_pair(2015, "Tom")); //使用pair插入
m1.insert(pair<int, string>(2015, "Tom"));
m1.insert({2015, "Tom"}); //initializer_list插入
m1.erase(key); //返回被移除的元素的数量
m1.erase(iter); //清除iter指向的元素
m1.erase(m1.begin()+2, m1.begin()+5); //清除某个区间

unordered_map/unordered_multimap

1
2
3
4
5
6
//基于哈希表实现,插入O(n),查找O(n),删除O(n)
//代价占用内存比map/multimap略大一点点,内部元素不排序
#include <unordered_map>

//大部分函数同map/multimap
//由于内部元素不排序,不能使用lower_bound和upper_bound

list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
list<int> l1 = l2;  //深拷贝构造
list<int> l1 = {0,1,2,3}; //initializer_list初始化
list<int> l1(l2.begin(), l2.end());
list<int> l1(7); //初始化有7个元素的list
list<int> l1(7, 3) //初始化有7个3的list

l1.clear(); //清空
l1.size(); //返回元素数量
l1.empty(); //是否为空

l1.front(); //访问第一个元素
l1.back(); //访问最后一个元素

l1.push_back(100); //末尾插入元素
l1.pop_back(); //清除末尾元素

iter = l1.insert(l1.begin(), 100); //在vector最前面插入100
iter = l1.insert(l1.begin(), l2.begin(), l2.end()); //插入另一个数组
iter = l1.erase(l1.begin()+2); //erase一个数
iter = l1.erase(l1.begin()+2, l1.begin()+5); //erase一个区间

基础输入输出

1
2
3
4
5
6
7
8
# include<string>
std::string str;
std::getline(std::cin, str); //会把'\n'去除
std::getline(std::cin, str, ' '); //设置分隔符,此时将空格视为一行的结束,'\n'会被读入
/*
立即在空白符分隔输入后使用时,例如在 int n; std::cin >> n; 后, getline 会用 operator>> 消耗掉留在输入流上的换行符,并立即返回。
常用解决方案是在切换到面向行输入前,用 cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 忽略输入行上所有剩下的字符。
*/

匿名函数

1
2
3
4
sort(v.begin(), v.end(),
[](const int& a, const int& b) {
return a < b;
});

评论