【问题标题】:Deciding when to use a hash table决定何时使用哈希表
【发布时间】:2017-02-27 09:26:57
【问题描述】:

我正在解决一个具有以下要求的竞争性编程问题:

我必须维护一个非 2d 点 (x,y) 的列表,唯一点的数量将少于 500。

我的想法是将它们存储在哈希表中(C++ 无序集是特定的),每次出现节点时,我都会查找表,如果节点不存在,我会插入它。

我还知道 我不会进行超过 500 次查找。 所以我看到一些解决方案只是搜索一个数组(未排序)并在插入之前检查节点是否已经存在。

我的问题是有什么合理的方法来猜测我应该何时使用哈希表而不是手动搜索键而无需对它们进行基准测试?

【问题讨论】:

  • 对等数据结构进行基准测试、分析并查看哪种方法最有效。

标签: c++ performance hashtable


【解决方案1】:

我的问题是有什么合理的方法来猜测我应该何时使用哈希表而不是手动搜索键而无需对它们进行基准测试?

我猜你熟悉基本算法 & time complexity 和 C++ standard containers 并且知道运气好的话哈希表访问是 O(1)

如果哈希表代码(或一些平衡的树代码,例如使用std::map - 假设键的顺序很简单)更具可读性,我更喜欢它,仅出于可读性的原因。

否则,考虑到approximate timing for various operations on a PC,您可能会做出一些猜测。顺便说一句,整个http:///norvig.com/21-days.html 页面都值得一读。

基本上,内存访问比 CPU 中的其他所有内容都要慢得多。 CPU cache 非常重要。典型的内存访问需要从 DRAM 模块中获取数据的高速缓存故障,其速度比一些基本算术运算或机器指令(例如,在寄存器中添加两个整数)慢数百倍。

实际上,只要您的数据很小(例如,少于一千个元素),这并不重要,因为在这种情况下,它很可能位于 L2 缓存中。

在数组中搜索(线性)非常快(因为缓存非常友好),最多可以搜索数千个(小)元素。

IIRC,Herb Sutter 在一些视频中提到,即使 插入 一个向量内的元素实际上 - 但不直观 - 比将其插入到一些中更快(考虑到移动切片所需的时间)平衡树(或者可能是其他一些容器,例如哈希表),最大容器大小为几千个小元素。这是在具有数兆字节缓存的典型平板电脑、台式机或服务器微处理器上。 YMMV。

如果你真的那么在意,就无法避免基准测试。

请注意,500 对整数可能适合 L1 缓存!

【讨论】:

    【解决方案2】:

    我的经验法则是假设处理器每秒可以处理 10^9 次操作。

    在您的情况下,只有 500 个条目。高达 O(N^2) 的算法可能是安全的。通过使用像向量这样的连续数据结构,您可以利用快速缓存命中。就常数而言,散列函数有时也会很昂贵。但是,如果您的数据大小为 10^6,则安全复杂度总共可能只有 O(N)。在这种情况下,您可能需要考虑 O(1) hashmap 进行单次查找。

    【讨论】:

      【解决方案3】:

      您可以使用 Big O Complexity 来粗略估计性能。对于哈希表,在最坏的情况下搜索元素的时间介于 O(1) 和 O(n) 之间。这意味着,在最好的情况下,您的访问时间与地图中元素的数量无关,但在最坏的情况下,它是线性的,取决于您的哈希表的大小。

      二叉树的搜索复杂度保证为 O(nlog(n))。这意味着,搜索元素始终取决于数组的大小,但在最坏的情况下,它比哈希表更快。

      您可以在这个方便的网站上查找一些 Big O Complexities:http://bigocheatsheet.com/

      【讨论】:

        猜你喜欢
        • 2011-03-04
        • 2014-12-22
        • 1970-01-01
        • 2021-08-13
        • 1970-01-01
        • 2016-07-11
        • 2021-08-30
        • 2023-03-31
        相关资源
        最近更新 更多