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++标准库》
本文详细介绍了C++标准模板库(STL)中的三种容器:set、map、unordered_set和unordered_map。深入探讨了这些容器的底层实现原理,如平衡二叉树和哈希表,以及它们提供的各种操作方法,如插入、查找、删除和遍历等。
1万+

被折叠的 条评论
为什么被折叠?



