std::unordered_set 如何分配桶以提供 O(1) 查找?
How does std::unordered_set allocate bucket to provide O(1) lookup?
unordered_set 应该提供 O(1) 查找时间以防散列函数良好。
每个桶包含具有相同哈希值的项目。
让我们假设我们的散列函数是理想的并且完全没有冲突。
哈希值可以从 0 到 max(std::size_t)。
如何在不为桶分配连续内存间隔的情况下组织 unordered_set 并提供 O(1) 查找?
我们不能分配连续的内存间隔,因为如果我们分配,那么我们只为几个哈希值使用大量内存——例如 0 和 1000000。
中间的值根本没有使用,但是我们为它们分配了内存。
Each bucket contains items with the same hash value.
错了。每个桶“包含”具有相同值的项目:
hash(key) % 当前桶数.
Let's assume that our hash function is ideal and gives no collisions at all.
在 pre-mod space 中没有碰撞并不一定是理想的:重要的是修改后的碰撞(或者如果有 power-of-2 桶计数则屏蔽,例如 Visual C++ ) 放入桶的数量。
Hash values can vary from 0 to max(std::size_t).
How to organize unordered_set without allocating continuous memory interval for buckets and to provide O(1) lookup?
当 table 有最大的 size()
时,通常每个 value/element 有 1 到 ~2 个桶。您可以通过调用 max_load_factor(float)
来确定 table 何时调整大小来稍微自定义它,但是您不能根据调整大小来自定义 - 这留给了实现。 GCC 通常会选择一个比当前大小的两倍大一点的素数。 Visual C++ 通常会加倍存储桶。
We can not allocate continuous memory interval because if we allocate then we use a lot of memory for only to several hash values - 0 and 1000000 for example.
Values in the middle are not used at all, but we allocated memory for them.
这忽略了将散列值修改为桶计数。 (它也忽略了稀疏数组的可行性,这可能是实用的,因为虚拟地址 space 可能比支持它的物理 RAM 大得多,但这不是散列 tables 的重点。)
unordered_set 应该提供 O(1) 查找时间以防散列函数良好。
每个桶包含具有相同哈希值的项目。
让我们假设我们的散列函数是理想的并且完全没有冲突。
哈希值可以从 0 到 max(std::size_t)。
如何在不为桶分配连续内存间隔的情况下组织 unordered_set 并提供 O(1) 查找?
我们不能分配连续的内存间隔,因为如果我们分配,那么我们只为几个哈希值使用大量内存——例如 0 和 1000000。
中间的值根本没有使用,但是我们为它们分配了内存。
Each bucket contains items with the same hash value.
错了。每个桶“包含”具有相同值的项目:
hash(key) % 当前桶数.
Let's assume that our hash function is ideal and gives no collisions at all.
在 pre-mod space 中没有碰撞并不一定是理想的:重要的是修改后的碰撞(或者如果有 power-of-2 桶计数则屏蔽,例如 Visual C++ ) 放入桶的数量。
Hash values can vary from 0 to max(std::size_t). How to organize unordered_set without allocating continuous memory interval for buckets and to provide O(1) lookup?
当 table 有最大的 size()
时,通常每个 value/element 有 1 到 ~2 个桶。您可以通过调用 max_load_factor(float)
来确定 table 何时调整大小来稍微自定义它,但是您不能根据调整大小来自定义 - 这留给了实现。 GCC 通常会选择一个比当前大小的两倍大一点的素数。 Visual C++ 通常会加倍存储桶。
We can not allocate continuous memory interval because if we allocate then we use a lot of memory for only to several hash values - 0 and 1000000 for example. Values in the middle are not used at all, but we allocated memory for them.
这忽略了将散列值修改为桶计数。 (它也忽略了稀疏数组的可行性,这可能是实用的,因为虚拟地址 space 可能比支持它的物理 RAM 大得多,但这不是散列 tables 的重点。)