3、无序集合unordered_set和无序字典unordered_map
下一篇:STL容器之string、stack、queue、bitset
1、有序集合set
set通常是由平衡二叉树实现出来(通常用红黑树实现),在二叉树中,每个节点都有一个父节点和两个子节点,左子树的所有元素都比自己小,右子树的所有元素都比自己大。set的主要优点是,它能很快找出一个具有某特定value的元素,因为它具备对数的复杂度,而对于循序式容器的复杂度是线性的。然而它的一个缺点是,你不能直接改变元素的value,因为那会破坏元素的自动排序。
set<int> s1 set<int> s1(op) set<int> s2 = s1 set<int> s2(s1) set<int> s2(beg, end) set<int> s2(beg, end, op) set<int> s2(initlist) set<int> s2 = initlist s2.~set() set<int> set<int, op> | 默认构造函数,建立一个空的set 建立一个空的set,以op作为排序规则 Copy构造函数,为相同类型的另一个set建立一份拷贝,所有元素均被复制 Copy构造函数,为相同类型的另一个set建立一份拷贝,所有元素均被复制 以区间内的元素作为初值,建立一个set 以区间内的元素为初值,以op为排序准则,建立一个set 以初值initlist的元素为初值建立一个set 以初值initlist的元素为初值建立一个set 销毁所有的元素,释放内存 一个set,以less<>(operator <)为排序准则 一个set,以op为排序准则 |
s.key_comp() | 返回“比较准则” |
s.value_comp() | 返回针对value的“比较准则”,和key_comp()相同 |
s.count(val) | 返回元素值为val 的元素个数 |
s.find(val) | 返回元素值为val 的第一个元素,如果找不到就返回end() |
s.lower_bound(val) | 返回val的第一个可安插位置,就是元素值>=val的第一个元素位置 |
s.upper_bound(val) | 返回val的最后一个可安插位置,就是元素值>val的第一个元素位置 |
s.equal_range(val) | 返回val可被安插的第一个位置和最后一个位置,就是元素值==val的元素区间 |
s1.swap(s2) | 交换s1和s2的数据 |
swap(s1, s2) | 交换s1和s2的数据 |
s.rbegin() | 返回反向iterator指向的反向迭代的第一个元素 |
s.rend() | 返回反向iterator指向的反向迭代最后一个元素的下一个位置 |
s.crbegin() | 返回const iterator反向迭代的第一个元素 |
s.crend() | 返回const iterator反向迭代的最后一个元素的下一个位置 |
s.insert(val) | 安插一个val拷贝,并返回新元素位置 |
s.insert(pos, val) | 安插val的拷贝,返回新元素位置,pos是个提示,指出安插动作的查找起点 |
s.insert(beg, end) | 将区间内所有元素拷贝到s,无返回值 |
s.insert(initlist) | 插入initlist所有元素,无返回值 |
s.emplace(args...) | 插入一个以args为初值的元素,并返回新元素位置 |
s.emplace_hind(pos, args...) | 插入一个以args为初值的元素,并返回新元素位置,pos是个提示,指出安插动作的查找起点 |
s.erase(val) | 移除与val相等的所有元素,返回被移除的元素个数 |
s.erase(pos) | 移除iterator位置pos上的元素,无返回值 |
s.erase(beg, end) | 移除区间内的所有元素,无返回值 |
2、有序字典map
map和set类似,通常由平衡二叉树完成,可以把set看作特殊的map,只不过set的key和value是同一对象。因此,map拥有set的所有能力和所有操作。唯一的区别是map的元素key/value的键值对,此外map可以作为关联式数组来运用。map会根据key自动对元素排序,这一性质使得map身上有一条重要限制:你不可以直接改变元素key,因为这会破坏正确次序,要修改元素的key,必须先移除拥有该key的元素,然后插入拥有新key/value的元素。
map<int> m1 map<int> m1(op) map<int> m2 = m1 map<int> m2(m1) map<int> m2(beg, end) map<int> m2(beg, end, op) map<int> m2(initlist) map<int> m2 = initlist m2.~map() map<key, val> map<key, val, op> | 默认构造函数,建立一个空的map 建立一个空的map,以op作为排序规则 Copy构造函数,为相同类型的另一个map建立一份拷贝,所有元素均被复制 Copy构造函数,为相同类型的另一个map建立一份拷贝,所有元素均被复制 以区间内的元素作为初值,建立一个map 以区间内的元素为初值,以op为排序准则,建立一个map 以初值initlist的元素为初值建立一个map 以初值initlist的元素为初值建立一个map 销毁所有的元素,释放内存 一个map,以less<>(operator <)为排序准则 一个map,以op为排序准则 |
m[key] | 如果关键字为key的元素不存在,则安插关键字为key的元素,如果不设置value,value默认初始化为0。如果存在则返回value值。 |
m.at(key) | 返回key对应的value,如果该元素不存在则抛出异常 |
for(auto iter = m.begin();iter!=m.end();iter++){ cout<<iter->first<<endl; cout<<iter->second<<endl; } | 遍历map中的所有元素 |
m.key_comp() | 返回“比较准则” |
m.value_comp() | 返回针对value的“比较准则”,和key_comp()相同 |
m.count(val) | 返回key为val 的元素个数 |
m.find(val) | 返回key为val 的第一个元素,如果找不到就返回end() |
m.lower_bound(val) | 返回key=val的第一个可安插位置,就是key>=val的第一个元素位置 |
m.upper_bound(val) | 返回key=val的最后一个可安插位置,就是key>val的第一个元素位置 |
m.equal_range(val) | 返回key=val可被安插的第一个位置和最后一个位置,就是key==val的元素区间 |
m1.swap(m2) | 交换m1和m2的数据 |
swap(m1, m2) | 交换m1和m2的数据 |
m.rbegin() | 返回反向iterator指向的反向迭代的第一个元素 |
m.rend() | 返回反向iterator指向的反向迭代最后一个元素的下一个位置 |
m.crbegin() | 返回const iterator反向迭代的第一个元素 |
m.crend() | 返回const iterator反向迭代的最后一个元素的下一个位置 |
m.insert(val) | 安插一个val拷贝,并返回新元素位置 |
m.insert(pos, val) | 安插val的拷贝,返回新元素位置,pos是个提示,指出安插动作的查找起点 |
m.insert(beg, end) | 将区间内所有元素拷贝到s,无返回值 |
m.insert(initlist) | 插入initlist所有元素,无返回值 |
m.emplace(args...) | 插入一个以args为初值的元素,并返回新元素位置 |
m.emplace_hind(pos, args...) | 插入一个以args为初值的元素,并返回新元素位置,pos是个提示,指出安插动作的查找起点 |
m.erase(val) | 移除与val相等的所有元素,返回被移除的元素个数 |
m.erase(pos) | 移除iterator位置pos上的元素,无返回值 |
m.erase(beg, end) | 移除区间内的所有元素,无返回值 |
3、无序集合unordered_set和无序字典unordered_map
- 无序容器的底层使用的是hash table,hash table所使用的解决碰撞的办法为拉链法,我们称hash table表格内的元素为桶(bucket),buckets的聚合体,则用vector完成,以便有动态扩充能力。
- 每个bucket维护一个链表,每个hash code被关联至一个链表中,这个链表时属于单链表还是双链表,取决于实现,C++的标准只保证它们的iterator至少是个forward iterator。因此反向的iterator,包括rbegin()、rend()、crbegin()、crend()都不提供。
- 使用hash table的优点是,如果拥有良好的hash策略,在安插、删除、查找元素时所用的时间为常量。
- 使用hash table的容器不提供“直接元素访问的操作”。
- 你可以指定bucket的最小数量。
- 你可以(并且有时候必须)提供自己的哈希函数。哈希函数是个函数或者仿函数,它接收一个元素类型的value作为参数,并返回一个size_t的value。因此,bucket的当前数量并未被考虑。将其返回的值映射到合法的bucket索引内,是由容器内部完成的。
- 你可以(并且有时候必须)提供自己的等价准则,它必须是个判断式。
- 你可以指定一个最大负载系数(最大负载系数 = 总元素个数 / bucket的个数),一旦超过就会自动rehashing。
- 你可以强迫rehashing,rehashing指的是重建hash table,即动态扩充bucket vector,并找出下一个新的并且足够大(大约两倍)的质数,检验旧表中的每个元素,计算其在新表中的位置,然后再插入到链表中。
(1)unordered容器的构造函数和析构函数如下:
Unord u | 默认构造函数,建立一个空的unordered容器 |
Unord u(bnum) | 建立一个空的unordered容器,至少使用bnum个bucket |
Uord u(bnum, hf, cmp) | 建立一个空的unordered容器,至少使用bnum个bucket,以hf作为哈希函数cmp作为等价准则 |
Uord u(u2) | 复制构造函数,建立u2的拷贝 |
Uord u = u2 | 复制构造函数,建立u2的拷贝 |
Uord u(beg, end) | 建立一个unordered容器,以[beg, end)元素作为初值 |
Uord u(beg, end, bnum) | 建立一个unordered容器,以[beg, end)元素作为初值,至少使用bnum个bucket |
Uord u(beg, end, bnum, hf) | 建立一个unordered容器,以[beg, end)元素作为初值,至少使用bnum个bucket,以hf作为哈希函数 |
Uord u(beg, end, bnum, hf, cmp) | 建立一个unordered容器,以[beg, end)元素作为初值,至少使用bnum个bucket,以hf作为哈希函数cmp作为等价准则 |
Uord u(initlist) | 建立一个unordered容器,以initlist作为初值 |
Uord u = initlist | 建立一个unordered容器,以initlist作为初值 |
u.~Uord() | 销毁所有元素并释放内存 |
(2)Unordered容器Uord的所有可能类型如下:
unorderd_set<elem> | 一个unordered_set,使用默认的哈希函数和默认比较函数 |
unorderd_set<elem, hash> | 一个unordered_set,使用hash作为哈希函数,使用默认比较函数 |
unorderd_set<elem, hash, cmp> | 一个unordered_set,使用hash作为哈希函数,使用cmp比较函数 |
unordered_map<key, T> | 一个unordered_map,使用默认的哈希函数和默认比较函数 |
unordered_map<key, T, hash> | 一个unordered_map,使用hash作为哈希函数,使用默认比较函数 |
unordered_map<key, T, hash, cmp> | 一个unordered_map,使用hash作为哈希函数,使用cmp比较函数 |
(3)除了STL容器简介中的公共函数以外,unordered容器的其它函数
u.hash_function() | 返回哈希函数 |
u.key_eq() | 返回比较函数 |
u.bucket_count() | 返回当前的bucket数量 |
u.bucket(val) | 返回val被找到的那个bucket编号 |
u.bucket_size(buckidx) | 返回第buckidx个bucket所含的元素个数 |
u.begin(buckidx) | 返回一个forward iterator,指向第buckidx个bucket中第一个元素 |
u.end(buckidx) | 返回一个forward iterator,指向第buckidx个bucket中最后个元素 |
u.cbegin(buckidx) | 返回一个const forward iterator,指向第buckidx个bucket中第一个元素 |
u.cend(buckidx) | 返回一个const forward iterator,指向第buckidx个bucket中最后个元素 |
u.max_bucket_count() | 返回bucket最大可能数量 |
u.load_factor() | 返回当前的负载系数 |
u.max_load_factor() | 返回当前最大的负载系数 |
u.max_load_factor(val) | 设定最大负载系数为val |
u.rehash(bnum) | 将容器rehash,使其bucket个数至少为bnum |
u.reserve(num) | 将容器rehash,使其空间至少可拥有num个元素 |
u1.swap(u2) | 交换u1和u2的数据 |
swap(u1, u2) | 交换u1和u2的数据 |
u.rbegin() | 返回反向iterator指向的反向迭代的第一个元素 |
u.rend() | 返回反向iterator指向的反向迭代最后一个元素的下一个位置 |
u.crbegin() | 返回const iterator反向迭代的第一个元素 |
u.crend() | 返回const iterator反向迭代的最后一个元素的下一个位置 |
u.insert(val) | 安插一个val拷贝,并返回新元素位置 |
u.insert(pos, val) | 安插val的拷贝,返回新元素位置,pos是个提示,指出安插动作的查找起点 |
u.insert(beg, end) | 将区间内所有元素拷贝到u,无返回值 |
u.insert(initlist) | 插入initlist所有元素,无返回值 |
u.emplace(args...) | 插入一个以args为初值的元素,并返回新元素位置 |
u.emplace_hind(pos, args...) | 插入一个以args为初值的元素,并返回新元素位置,pos是个提示,指出安插动作的查找起点 |
u.erase(val) | 移除与val相等的所有元素,返回被移除的元素个数 |
u.erase(pos) | 移除iterator位置pos上的元素,无返回值 |
u.erase(beg, end) | 移除区间内的所有元素,无返回值 |
u[key] | 安插一个带着key的元素——如果尚未存在于容器内。返回一个reference指向带着key的元素 |
u.at(key) | 返回一个reference指向带着key的元素 |
参考:《C++标准库》