map

如果只是 map 则有序

初始化

map<int, int> m1;  // 空
map<int, int> m2({{1, 2}, {3, 4}});  // 带值初始化

说到 map 会有序,他会帮你升序,如果想要降序或者自定义顺序,那可以再传入一个函数对象

map<int, int, greater<int>> m3;
 
struct myGreater {
	bool operator() (const int &a, const int &b) const {
		return a > b;
	}
}
map<int, int, myGreater> m3;

如此以来就逆序了。不过只能对 key 进行排序,想再自由一点,就得转成 vector 自己操作了

函数对象的理解

排序就是想要升序,默认是比小,可以理解为,aRb,出 1 则 a 前

在这里,出 1 说明 a 大,靠前,便是降序

另外,这里要给 operator()const

operator[]

潜在的增加元素

如果访问某个不存在的 key 下的元素,会返回默认空值 (0,“”),同时这样创造了一个空位,导致凭空增加了

因此它可以用来插入新值和覆盖旧值,insert 则只能插入新值

[] 返回默认值,at 则会抛出异常

迭代器

使用 for-range 循环,每趟循环的元素是一个 key val pair

使用迭代器循环就是类指针,指的 pair

erase

可以用 clear 直接删,也可以传入迭代器用 erase

find ; count

函数位置

vector 这种序列式容器,要用 find(begin, end, val) 的外面的函数

而关联容器如 map,则成员函数就行了 map.find(key)

find 返回迭代器,找不到返回 end 迭代器

值得注意的是,map set 这类,有唯一属性的,count 只会返回 0 和 1,相当于用来表示存不存在了

unordered_map

需要自己对应的头文件,可用的成员函数基本还是那些

可以比较一下两者的实现:map 是红黑树,unordered_map 是哈希表

unordered_map 也可以提供第三参数,一个函数对象,表示哈希的方法,运用于自己的类,不过自己的类还需要重载 operator==

哈希表

换句话说,当我们提到哈希表的时候,要想到的是 unordered_map

二分查找

对应库函数,下标就是迭代器,可以通过 -nums.begin 实现索引计算

lower_bound

target 在就 target 的迭代器,不在就在大一个的位置

可以理解为找得到就找得到,找不到就是插入的位置

upper_bound

就是雷打不动大于 target 的位置

然后去看看具体实现,其实就是上述实现中,把相等的情况给另一类

equal_range

返回 pair<lower, upper>

布尔值,只帮你判断有没有

set

我感觉可以理解为只有 key 的 map,所以很多操作类似,也有 unordered_set

然后没有 [] 了,用 insert

stack

也可以用 initializer_list 初始化

push

pop

注意,void,只会删除,不看内容

top

只有这一个接口看内容

size

empty

queue

pop

注意,void,只会删除,不看内容

front / back

有两个接口看内容

vector

这个的初始化还是得学学,自己构造啊之类的,不知道 initializer_list 能不能直接用

其他函数

*max_element(begin, end)
sort
to_string(int)
min({1, 2, 3})
str.substr(begin, len)
#include <climits>
INT_MIN;
LLONG_MAX;
LONG_MAX;