转载自 这里
目录
std::erase_if (std::unordered_map)
简介
本篇博客介绍C++常用的无序关联容器unordered_map。unordered_map是C++11正式加入的对hash_map的官方实现(之前标准C++没有hash_map的官方实现,我们使用的STL的hash_map并不是官方的)。从名字可以看出这个结构是无序的,底层设计思想和STL的hash_map一样。元素在内部不以任何特定顺序排序,而是放进桶中。元素放进哪个桶完全依赖于其键的哈希。这允许对单独元素的快速访问,因为一旦计算哈希,则它准确指代元素所放进的桶。unordered_map搜索、插入和元素移除拥有平均常数时间复杂度。
查找元素
at()用于访问指定元素
-
T& at( const Key& key );
-
const T& at( const Key& key ) const;
返回到等于 key 的键的元素的引用。若无该元素,则抛出 std::out_of_range 类型异常。
operator []用于访问或插入元素
-
T& operator[]( const Key& key );
-
T& operator[]( Key&& key );
返回等于 key 的键的值的引用。如果该键不存在,则执行插入,反之,则覆盖原来的值。
-
#include <iostream>
-
#include <string>
-
#include <vector>
-
#include <unordered_map>
-
int main()
-
{
-
std::unordered_map<char, int> letter_counts {{'a', 27}, {'b', 3}, {'c', 1}};
-
std::cout << "initially:\n";
-
for (const auto &pair : letter_counts) {
-
std::cout << pair.first << ": " << pair.second << '\n';
-
}
-
letter_counts['b'] = 42; // 更新既存值
-
letter_counts['x'] = 9; // 插入新值
-
std::cout << "after modifications:\n";
-
for (const auto &pair : letter_counts) {
-
std::cout << pair.first << ": " << pair.second << '\n';
-
}
-
// 统计每个词的出现数
-
// (首次调用 operator[] 以零初始化计数器)
-
std::unordered_map<std::string, size_t> word_map;
-
for (const auto &w : { "this", "sentence", "is", "not", "a", "sentence",
-
"this", "sentence", "is", "a", "hoax"}) {
-
++word_map[w];
-
}
-
for (const auto &pair : word_map) {
-
std::cout << pair.second << " occurrences of word '" << pair.first << "'\n";
-
}
-
}
-
输出:
-
initially:
-
a: 27
-
b: 3
-
c: 1
-
after modifications:
-
a: 27
-
b: 42
-
c: 1
-
x: 9
-
2 occurrences of word 'a'
-
1 occurrences of word 'hoax'
-
2 occurrences of word 'is'
-
1 occurrences of word 'not'
-
3 occurrences of word 'sentence'
-
2 occurrences of word 'this'
count() 返回特定键的元素数量
-
(1)size_type count( const Key& key ) const;
-
(2)template< class K >
-
size_type count( const K& x ) const;
(1) 返回等于指定参数 key 的键的元素数,因为此容器不允许重复,故返回值为 0 或 1 。
(2) 返回键等于指定参数 x 的元素数。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。
find()寻找特定键的元素
-
(1)iterator find( const Key& key );
-
(2)const_iterator find( const Key& key ) const;
-
(3)template< class K > iterator find( const K& x );
-
(4)template< class K > const_iterator find( const K& x ) const;
(1-2) 寻找键等于 key 的的元素。
(3-4) 寻找键等于值 x 的元素。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。
-
#include <iostream>
-
#include <unordered_map>
-
int main()
-
{
-
// 简单比较演示
-
std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};
-
auto search = example.find(2);
-
if (search != example.end()) {
-
std::cout << "Found " << search->first << " " << search->second << '\n';
-
} else {
-
std::cout << "Not found\n";
-
}
-
}
-
输出:
-
Found 2 b
contains()可检查容器是否含有特定键的元素
-
(1)bool contains( const Key& key ) const;
-
(2)template< class K > bool contains( const K& x ) const;
(1) 检查容器中是否有键等于 key 的元素。
(2) 检查是否有键等于值 x 的元素。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。
-
#include <iostream>
-
#include <unordered_map>
-
int main()
-
{
-
std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};
-
if (example.contains(2)) {
-
std::cout << "Found\n";
-
} else {
-
std::cout << "Not found\n";
-
}
-
}
-
输出:
-
Found
find()的返回值是迭代器,若有元素,可以直接通过返回的迭代器获取元素信息。 而contains()的返回值是bool型,只用于确定是否包含该元素。
equal_range()返回匹配特定键的元素范围
-
(1)std::pair<iterator,iterator> equal_range( const Key& key );
-
(2)std::pair<const_iterator,const_iterator> equal_range( const Key& key ) const;
-
(3)template< class K >
-
std::pair<iterator,iterator> equal_range( const K& x );
-
(4)template< class K >
-
std::pair<const_iterator,const_iterator> equal_range( const K& x ) const;
(1-2) 返回容器中所有键等于 key 的元素范围。范围以两个迭代器定义,第一个指向所需范围的首元素,而第二个指向范围的尾后一位元素。
(3-4) 返回含有容器中所有键等于 x 的元素的范围。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。
-
#include <iostream>
-
#include <unordered_map>
-
int main()
-
{
-
std::unordered_map<int,char> map = {{1,'a'},{1,'b'},{1,'d'},{2,'b'}};
-
auto range = map.equal_range(1);
-
for (auto it = range.first; it != range.second; ++it) {
-
std::cout << it->first << ' ' << it->second << '\n';
-
}
-
}
-
输出:
-
1 a
迭代器
begin() & cbegine()
-
iterator begin() noexcept;
-
const_iterator begin() const noexcept;
-
const_iterator cbegin() const noexcept;
返回指向 unordered_map 首元素的迭代器。若 unordered_map 为空,则返回的迭代器将等于 end()。
end() & cend()
-
iterator end() noexcept;
-
const_iterator end() const noexcept;
-
const_iterator cend() const noexcept;
返回指向 unordered_map 最后一个元素的之后的迭代器。此元素表现为占位符;试图访问它导致未定义行为。
-
#include <cmath>
-
#include <iostream>
-
#include <unordered_map>
-
struct Node { double x, y; };
-
int main() {
-
Node nodes[3] = { {1, 0}, {2, 0}, {3, 0} };
-
// mag 是将 Node 的地址映射到其在平面中的模的映射
-
std::unordered_map<Node *, double> mag = {
-
{ nodes, 1 },
-
{ nodes + 1, 2 },
-
{ nodes + 2, 3 }
-
};
-
// 将每个 y 坐标从 0 更改到模
-
for(auto iter = mag.begin(); iter != mag.end(); ++iter){
-
auto cur = iter->first; // 指向 Node 的指针
-
cur->y = mag[cur]; // 可以也使用 cur->y = iter->second;
-
}
-
// 更新并打印每个结点的模
-
for(auto iter = mag.begin(); iter != mag.end(); ++iter){
-
auto cur = iter->first;
-
mag[cur] = std::hypot(cur->x, cur->y);
-
std::cout << "The magnitude of (" << cur->x << ", " << cur->y << ") is ";
-
std::cout << iter->second << '\n';
-
}
-
// 以基于范围的 for 循环重复上述者
-
for(auto i : mag) {
-
auto cur = i.first;
-
cur->y = i.second;
-
mag[cur] = std::hypot(cur->x, cur->y);
-
std::cout << "The magnitude of (" << cur->x << ", " << cur->y << ") is ";
-
std::cout << mag[cur] << '\n';
-
// 注意与 std::cout << iter->second << '\n'; 相反,上述的
-
// std::cout << i.second << '\n'; 不会打印更新的模
-
}
-
}
-
输出:
-
The magnitude of (1, 1) is 1.41421
-
The magnitude of (2, 2) is 2.82843
-
The magnitude of (3, 3) is 4.24264
-
The magnitude of (1, 1.41421) is 1.73205
-
The magnitude of (2, 2.82843) is 3.4641
-
The magnitude of (3, 4.24264) is 5.19615
容量
empty() 用于检查容器是否为空
-
bool empty() const noexcept;
-
[[nodiscard]] bool empty() const noexcept;
size() 返回容纳的元素数量
size_type size() const noexcept;
返回容器中的元素数,即std::distance(begin(), end()) 。
-
int main()
-
{
-
std::unordered_map<int,char> nums {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
-
std::cout << "nums contains " << nums.size() << " elements.\n";
-
}
-
输出:
-
nums contains 4 elements.
max_size() 返回最大可容纳的元素数
size_type max_size() const noexcept;
返回根据系统或库实现限制的容器可包含的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。
-
#include <iostream>
-
#include <unordered_map>
-
int main()
-
{
-
std::unordered_map<char,char> s;
-
std::cout << "Maximum size of a 'unordered_map' is " << s.max_size() << "\n";
-
}
-
输出:
-
Maximum size of a 'unordered_map' is 768614336404564650
修改操作
clear()
void clear() noexcept;
从容器去除所有元素。此调用后 size() 返回零。非法化任何指代所含元素的引用、指针或迭代器。可能亦非法化尾后迭代器。
insert()
-
(1)std::pair<iterator,bool> insert( const value_type& value );
-
std::pair<iterator,bool> insert( value_type&& value );
-
(2)template< class P >
-
std::pair<iterator,bool> insert( P&& value );
-
(3)iterator insert( const_iterator hint, const value_type& value );
-
iterator insert( const_iterator hint, value_type&& value );
-
(4)template< class P >
-
iterator insert( const_iterator hint, P&& value );
-
(5)template< class InputIt >
-
void insert( InputIt first, InputIt last );
-
(6)void insert( std::initializer_list<value_type> ilist );
-
(7)insert_return_type insert(node_type&& nh);
-
(8)iterator insert(const_iterator hint, node_type&& nh);
若容器尚未含有带等价关键的元素,则插入元素到容器中。
(1-2) 插入 value 。重载 (2) 等价于 emplace(std::forward<P>(value)) ,且仅若 std::is_constructible<value_type, P&&>::value == true 才参与重载决议。
(3-4) 插入 value ,以 hint 为应当开始搜索的位置的非强制建议。重载 (4) 等价于 emplace_hint(hint, std::forward<P>(value)) ,且仅若 std::is_constructible<value_type, P&&>::value == true 才参与重载决议。
(5) 插入来自范围 [first, last) 的元素。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的。
(6) 插入来自 initializer_list ilist 的元素。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的。
(7) 若 nh 是空的结点句柄,则不做任何事。否则插入 nh 所占有的元素到容器,若容器尚未含有拥有等价于 nh.key() 的关键的元素。若 nh 非空且 get_allocator() != nh.get_allocator() 则行为未定义。
(8) 若 nh 是空的结点句柄,则不做任何事并返回尾迭代器。否则,插入 nh 所占有的元素到容器,若容器尚未含有拥有等价于 nh.key() 的关键的元素,并返回指向拥有等于 nh.key() 的关键的元素的迭代器(无关乎插入成功还是失败)。若插入成功,则从 nh 移动,否则它保持该元素的所有权。元素被插入到尽可能接近 hint 的位置。若 nh 非空且 get_allocator() != nh.get_allocator() 则行为未定义。
若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不受影响。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。若插入成功,则在结点把柄保有元素时获得的指向该元素的指针和引用被非法化,而在提取前获得的指向元素的指针和引用变得合法。
-
#include <string>
-
#include <iostream>
-
#include <unordered_map>
-
int main ()
-
{
-
std::unordered_map<int, std::string> dict = {{1, "one"}, {2, "two"}};
-
dict.insert({3, "three"});
-
dict.insert(std::make_pair(4, "four"));
-
dict.insert({{4, "another four"}, {5, "five"}});
-
bool ok = dict.insert({1, "another one"}).second;
-
std::cout << "inserting 1 -> \"another one\" "
-
<< (ok ? "succeeded" : "failed") << '\n';
-
std::cout << "contents:\n";
-
for(auto& p: dict)
-
std::cout << " " << p.first << " => " << p.second << '\n';
-
}
-
输出:
-
inserting 1 -> "another one" failed
-
contents:
-
5 => five
-
1 => one
-
2 => two
-
3 => three
-
4 => four
insert_or_assign()
-
(1)template <class M>
-
pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
-
(2)template <class M>
-
pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
-
(3)template <class M>
-
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
-
(4)template <class M>
-
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
(1,3) 若等价于 k 的键已存在于容器中,则赋值 std::forward<M>(obj) 给对应于键 k 的 mapped_type 。若键不存在,则如同用 insert 插入从 value_type(k, std::forward<M>(obj)) 构造的新值。
(2,4) 同 (1,3) ,除了从 value_type(std::move(k), std::forward<M>(obj)) 构造被映射值。
若插入发生且导致容器的重哈希,则所有迭代器被非法化。否则迭代器不受影响。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。
-
#include <iostream>
-
#include <unordered_map>
-
#include <string>
-
int main()
-
{
-
std::unordered_map<std::string, std::string> myMap;
-
myMap.insert_or_assign("a", "apple" );
-
myMap.insert_or_assign("b", "bannana" );
-
myMap.insert_or_assign("c", "cherry" );
-
myMap.insert_or_assign("c", "clementine");
-
for (const auto &pair : myMap) {
-
std::cout << pair.first << " : " << pair.second << '\n';
-
}
-
}
-
输出:
-
c : clementine
-
a : apple
-
b : bannana
emplace()
-
template< class... Args >
-
std::pair<iterator,bool> emplace( Args&&... args );
若容器中无拥有该关键的元素,则插入以给定的 args 原位构造的新元素到容器。
细心地使用 emplace 允许在构造新元素的同时避免不必要的复制或移动操作。 准确地以与提供给 emplace 者相同的参数,通过std::forward<Args>(args)... 转发调用新元素(即 std::pair<const Key, T> )的构造函数。 即使容器中已有拥有该关键的元素,也可能构造元素,该情况下新构造的元素将被立即销毁。
若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不被非法化。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。
-
#include <iostream>
-
#include <utility>
-
#include <string>
-
#include <unordered_map>
-
int main()
-
{
-
std::unordered_map<std::string, std::string> m;
-
// 使用 pair 的移动构造函数
-
m.emplace(std::make_pair(std::string("a"), std::string("a")));
-
// 使用 pair 的转换移动构造函数
-
m.emplace(std::make_pair("b", "abcd"));
-
// 使用 pair 的模板构造函数
-
m.emplace("d", "ddd");
-
// 使用 pair 的逐片构造函数
-
m.emplace(std::piecewise_construct,
-
std::forward_as_tuple("c"),
-
std::forward_as_tuple(10, 'c'));
-
// C++17 起,能使用 m.try_emplace("c", 10, 'c');
-
for (const auto &p : m) {
-
std::cout << p.first << " => " << p.second << '\n';
-
}
-
}
-
输出:
-
a => a
-
b => abcd
-
c => cccccccccc
-
d => ddd
-
#include <unordered_map>
-
#include <iostream>
-
#include <utility>
-
int main()
-
{
-
std::unordered_map<int, int> numbers;
-
std::cout << "Initially, numbers.empty(): " << numbers.empty() << '\n';
-
numbers.emplace(42, 13);
-
numbers.insert(std::make_pair(13317, 123));
-
std::cout << "After adding elements, numbers.empty(): " << numbers.empty() << '\n';
-
}
-
输出:
-
Initially, numbers.empty(): 1
-
After adding elements, numbers.empty(): 0
emplace_hint()
-
template <class... Args>
-
iterator emplace_hint( const_iterator hint, Args&&... args );
插入新元素到容器,以 hint 为应当放置新元素位置的建议。原位构造元素,即不进行复制或移动操作。
准确地以与提供给函数者相同的参数,以 std::forward<Args>(args)... 转发调用元素类型( value_type 即 std::pair<const Key, T> )的构造函数。
若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不被非法化。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。
try_emplace()
-
(1)template <class... Args>
-
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
-
(2)template <class... Args>
-
pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
-
(3)template <class... Args>
-
iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
-
(4)template <class... Args>
-
iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
(1) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。
(2) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(std::move(k)), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。
(3) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace_hint ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。
(4) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace_hint ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(std::move(k)), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。
若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不被非法化。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。
-
#include <iostream>
-
#include <utility>
-
#include <string>
-
#include <unordered_map>
-
int main()
-
{
-
using namespace std::literals;
-
std::unordered_map<std::string, std::string> m;
-
m.try_emplace("a", "a"s);
-
m.try_emplace("b", "abcd");
-
m.try_emplace("c", 10, 'c');
-
m.try_emplace("c", "Won't be inserted");
-
for (const auto &p : m) {
-
std::cout << p.first << " => " << p.second << '\n';
-
}
-
}
-
输出:
-
a => a
-
b => abcd
-
c => cccccccccc
erase()
-
(1)iterator erase( const_iterator pos );
-
(2)iterator erase( const_iterator first, const_iterator last );
-
(3)size_type erase( const key_type& key );
从容器移除指定的元素。
(1) 移除位于 pos 的元素。
(2) 移除范围 [first; last) 中的元素,它必须是 *this 中的合法范围。
(3) 移除键等于 key 的元素(若存在一个)。
到被去除元素的引用和迭代器被非法化,其他迭代器和引用不被非法化。迭代器 pos 必须合法且可解引用,从而使得 end() 迭代器(合法,但不可解引用)不能用作 pos 所用的值。保留未被擦除的元素顺序(这使得可能在迭代通过容器时擦除单独的元素)。
-
#include <unordered_map>
-
#include <iostream>
-
int main()
-
{
-
std::unordered_map<int, std::string> c = {{1, "one"}, {2, "two"}, {3, "three"},
-
{4, "four"}, {5, "five"}, {6, "six"}};
-
// 从 c 擦除所有奇数
-
for(auto it = c.begin(); it != c.end(); )
-
if(it->first % 2 == 1)
-
it = c.erase(it);
-
else
-
++it;
-
for(auto& p : c)
-
std::cout << p.second << ' ';
-
}
-
输出:
-
two four six
swap()
-
void swap( unordered_map& other );
-
void swap( unordered_map& other ) noexcept();
将内容与 other 的交换,不在单个元素上调用任何移动、复制或交换操作。所有迭代器和引用保持合法,尾后迭代器被非法化。
Hash 和 KeyEqual 对象必须可交换 (Swappable) ,并用非成员 swap 的非限定调用交换它们。
extract()
-
(1)node_type extract( const_iterator position );
-
(2)node_type extract( const key_type& x );
(1) 解链含 position 所指向元素的结点并返回占有它的结点句柄。
(2) 若容器拥有元素而其关键等于 x ,则从容器解链该元素并返回占有它的结点句柄。否则,返回空结点把柄。任何情况下,均不复制或移动元素,只重指向容器结点的内部指针。
释出结点只会非法化指向被释出元素的迭代器,并保持未被去除元素的相对顺序。指向被释出元素的指针和引用保持合法,但在结点句柄占有该元素时不能使用:若元素被插入容器,就能使用它们。
注意:extract 是更换键而不重分配的唯一方式。
-
unordered_map<int, string> m{{1, "mango"}, {2, "papaya"}, {3, "guava"}};
-
auto nh = m.extract(2);
-
nh.key() = 4;
-
m.insert(move(nh));
merge()
-
(1)template<class H2, class P2>
-
void merge(std::unordered_map<Key, T, H2, P2, Allocator>& source);
-
(2)template<class H2, class P2>
-
void merge(std::unordered_map<Key, T, H2, P2, Allocator>&& source);
-
(3)template<class H2, class P2>
-
void merge(std::unordered_multimap<Key, T, H2, P2, Allocator>& source);
-
(4)template<class H2, class P2>
-
void merge(std::unordered_multimap<Key, T, H2, P2, Allocator>&& source);
试图释出("接合") source 中每个元素,并用 *this 的哈希函数和关键相等谓词插入到 *this 。 若 *this 中有元素,其关键等价于来自 source 中元素的关键,则不从 source 释出该元素。 不复制或移动元素,只会重指向容器结点的内部指针。指向被转移元素的所有指针和引用保持合法,但现在指代到 *this 中而非到 source 中。指代被转移元素的迭代器和所有指代到 *this 的迭代器被非法化。指向留在 source 中元素的迭代器保持合法。若 get_allocator() != source.get_allocator() 则行为未定义。
通接口
begin() & cbegin()
-
local_iterator begin( size_type n );
-
const_local_iterator begin( size_type n ) const;
-
const_local_iterator cbegin( size_type n ) const;
返回指向下标为 n 的桶首元素的迭代器。
end() & cend()
-
local_iterator end( size_type n );
-
const_local_iterator end( size_type n ) const;
-
const_local_iterator cend( size_type n ) const;
返回后随下标为 n 的桶的最后元素的元素的迭代器。此元素表现为占位符,试图访问它会导致未定义行为。
bucket_count() 返回容器中的桶数
size_type bucket_count() const;
max_bucket_count() 返回容器由于系统或库实现限制的能保有的最大桶数
size_type max_bucket_count() const;
bucket_size() 返回下标为 n 的桶中的元素数
size_type bucket_size( size_type n ) const;
bucket() 返回关键 key 的桶的下标
size_type bucket( const Key& key ) const;
始终会在此桶中找到关键等于 key 的元素(若存在)。返回值仅对 bucket_count() 返回相同值的容器实例合法。若 bucket_count() 为零则行为未定义。
哈希策略
load_factor()
float load_factor() const;
返回每个桶元素的平均数,即 size() 除以 bucket_count() 。
max_load_factor()
-
(1)float max_load_factor() const;
-
(2)void max_load_factor( float ml );
管理最大加载因子(每个桶的平均元素数)。若加载因子超出此阈值,则容器自动增加桶数。
(1) 返回最大加载因子。
(2) 设置最大加载因子为 ml 。
rehash()
void rehash( size_type count );
设置桶数为 count 并重哈希容器,即考虑桶总数已改变,再把元素放到适当的桶中。若新的桶数使加载因子大于最大加载因子( count < size() / max_load_factor() ),则新桶数至少为 size() / max_load_factor() 。
reserve()
void reserve( size_type count );
设置桶数为适应至少 count 个元素,而不超出最大加载因子所需的数,并重哈希容器,即考虑桶数已更改后将元素放进适合的桶。等效地调用 rehash(std::ceil(count / max_load_factor())) 。
观察器
hash_function() 返回对关键哈希的函数
hasher hash_function() const;
key_eq() 返回比较关键相等性的函数
key_equal key_eq() const;
std::swap(std::unordered_map)
-
(1)template< class Key, class T, class Hash, class KeyEqual, class Alloc >
-
void swap( unordered_map<Key,T,Hash,KeyEqual,Alloc>& lhs,
-
unordered_map<Key,T,Hash,KeyEqual,Alloc>& rhs );
-
(2)template< class Key, class T, class Hash, class KeyEqual, class Alloc >
-
void swap( unordered_map<Key,T,Hash,KeyEqual,Alloc>& lhs,
-
unordered_map<Key,T,Hash,KeyEqual,Alloc>& rhs ) noexcept(/* see below */);
为 std::unordered_map 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。
std::erase_if (std::unordered_map)
-
template< class Key, class T, class Hash, class KeyEqual, class Alloc, class Pred >
-
typename std::unordered_map<Key,T,Hash,KeyEqual,Alloc>::size_type
-
erase_if(std::unordered_map<Key,T,Hash,KeyEqual,Alloc>& c, Pred pred); (C++20 起)
从容器中去除所有满足谓词 pred 的元素。等价于:
-
auto old_size = c.size();for (auto i = c.begin(), last = c.end(); i != last; ) {
-
if (pred(*i)) {
-
i = c.erase(i);
-
} else {
-
++i;
-
}}
-
return old_size - c.size();