滥用 O(1) 哈希查找的缺点 table?
Down sides of abusing O(1) lookup of a hash table?
哈希 table 是非常常见的数据结构,用于在竞争 programming/interviews.
中出现的编码问题
Hash tables 采用键值对,以便您可以查找键并获取值。但是,我经常发现自己需要 O(1)
查找键而不是真正关心值。
例如:
如果我需要知道一些 strings
以前是否被使用过,我可能会将它们插入一个散列 table 和 key: string
,value: bool
其中的值布尔值始终为真。
这样做的缺点是什么?是否有其他数据结构提供不需要键值对的 O(1) 查找?
如果此容器的唯一目的是测试字符串是否已被使用,那么 unordered_set(唯一键的集合,按键散列)就可以了。
Unordered set is an associative container that contains a set of
unique objects of type Key. Search, insertion, and removal have
average constant-time complexity.
您应该按照预期的方式使用数据结构。然后您可以分析您的代码以查看性能是否足够。如果不是,则优化瓶颈。
话虽如此,检查字符串是否已被使用的更好的数据结构是 std::unordered_set or std::set. Your use case is a typical use case for a set data structure. Wikipedia:
In computer science, a set is an abstract data type that can store
unique values, without any particular order. It is a computer
implementation of the mathematical concept of a finite set. Unlike
most other collection types, rather than retrieving a specific element
from a set, one typically tests a value for membership in a set.
除非你有一个完美的散列算法,否则你会发生冲突。到那时,您必须查看实际的哈希 table 实现。每个都有自己的优点和缺点,目前所有 std::unordered_map
(和 std::unordered_set
?)都实现为带有链表的桶,这会使您的 O(1) 变成最坏的 O(N) 情况。
平均值仍然是 O(1),因此如果您的系统对时间要求不高并且您使用了良好的散列,那么几年前字符串的散列使用了一些学术上接受的良好算法,然后使用散列集。另一方面,如果您无法接受最坏情况 O(N) 查找,请使用 std::map
或 std::set
.
- 注意 1:所有哈希 table 都有一个致命弱点,这使得它们在最坏情况下的复杂度为 O(N),除非您的存储桶是作为平衡树实现的。
- 注2:完美哈希是没有冲突的。
- 注3:有一些文献可以告诉我们如何从已知数据中得到一个完美的散列,还没有看到任何关于未知数据的完美散列。
- 注4:如果你找到后者,那么你或许可以证明P = NP。
哈希 table 是非常常见的数据结构,用于在竞争 programming/interviews.
中出现的编码问题Hash tables 采用键值对,以便您可以查找键并获取值。但是,我经常发现自己需要 O(1)
查找键而不是真正关心值。
例如:
如果我需要知道一些 strings
以前是否被使用过,我可能会将它们插入一个散列 table 和 key: string
,value: bool
其中的值布尔值始终为真。
这样做的缺点是什么?是否有其他数据结构提供不需要键值对的 O(1) 查找?
如果此容器的唯一目的是测试字符串是否已被使用,那么 unordered_set(唯一键的集合,按键散列)就可以了。
Unordered set is an associative container that contains a set of unique objects of type Key. Search, insertion, and removal have average constant-time complexity.
您应该按照预期的方式使用数据结构。然后您可以分析您的代码以查看性能是否足够。如果不是,则优化瓶颈。
话虽如此,检查字符串是否已被使用的更好的数据结构是 std::unordered_set or std::set. Your use case is a typical use case for a set data structure. Wikipedia:
In computer science, a set is an abstract data type that can store unique values, without any particular order. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set.
除非你有一个完美的散列算法,否则你会发生冲突。到那时,您必须查看实际的哈希 table 实现。每个都有自己的优点和缺点,目前所有 std::unordered_map
(和 std::unordered_set
?)都实现为带有链表的桶,这会使您的 O(1) 变成最坏的 O(N) 情况。
平均值仍然是 O(1),因此如果您的系统对时间要求不高并且您使用了良好的散列,那么几年前字符串的散列使用了一些学术上接受的良好算法,然后使用散列集。另一方面,如果您无法接受最坏情况 O(N) 查找,请使用 std::map
或 std::set
.
- 注意 1:所有哈希 table 都有一个致命弱点,这使得它们在最坏情况下的复杂度为 O(N),除非您的存储桶是作为平衡树实现的。
- 注2:完美哈希是没有冲突的。
- 注3:有一些文献可以告诉我们如何从已知数据中得到一个完美的散列,还没有看到任何关于未知数据的完美散列。
- 注4:如果你找到后者,那么你或许可以证明P = NP。