【问题标题】:Hash that returns the same value for all numbers in range?为范围内的所有数字返回相同值的哈希?
【发布时间】:2017-11-03 15:43:42
【问题描述】:

我正在解决一个问题,即我始终在内存中拥有数据库中的整个表,其中包含 9 位数字的低范围和高范围。我得到了一个 9 位数字,我需要使用它来根据该数字是否在该范围内来查找表中的其余列。例如,如果范围是 100,000,000 到 125,000,000 并且给了我一个数字 117,123,456,那么我会知道我在 100-125 百万范围内,并且任何指向的数据向量都是我将使用的。

现在我能想到的最好的查找时间是 log(n) 运行时间。这没关系,充其量是,但仍然很慢。该表至少有 100,000 个条目,每次执行此应用程序(每天 10 次以上),我都需要在该表中查找数万次(如果不是十万次)的值。

所以我想知道是否可以使用 unordered_set 代替,编写我自己的 Hash 函数,该函数总是为范围内的每个数字返回相同的哈希值。使用上面的相同示例,从 100,000,000 到 125,000,000 将始终返回例如 AB12CD 的哈希值。然后当我使用查找值 117,123,456 时,我会得到相同的 AB12CD 哈希,并且查找时间为 O(1)。

这可能吗,如果可以,有什么想法吗?

提前致谢。

【问题讨论】:

  • 范围是否等间隔?范围是连续的吗?例如:0 - 1000、1000 - 2000、2000- 3000...
  • 您想编写自己的完美哈希函数以避免冲突吗?您是否尝试过使用默认的std::unordered_map
  • @stack_n_queue 不幸的是没有。在某些情况下,范围是 1。在其他情况下,范围是数百万。
  • @Snps 我觉得你还没有理解我想要表达的想法。我正在使用无序映射,但是我不希望无序映射中有 10 亿个条目。我希望地图为每个 RANGE 条目返回不同的哈希值。
  • Log2(100,000) 大约是 17,17 次比较几乎没有。使用排序的向量,而不是地图。

标签: c++ algorithm hash hashmap


【解决方案1】:

是的。假设您可以按顺序编号间隔,您可以将多项式拟合到您的截止值,并从多项式接收索引值。例如,截止值为 100,000,000、125,000,000、250,000,000 和 327,000,000,您可以使用点 (100, 0)、(125, 1)、(250, 2) 和 (327, 3),将一阶导数限制为 [ 0, 1]。假设您的区间表现得体,您将能够将其与 N 个截止的 (N+2) 次多项式拟合。

有一张所需哈希值的表;使用 floor[polynomial(i)] 作为表中的索引。

【讨论】:

  • 评估这个多项式不会比只进行二分搜索慢吗?
  • 可能,是的......但它是 O(1),这是当前的问题。
  • 度数真的是O(1)吗?从 OP 描述的方式来看,我认为表格大小可能会有所不同。
  • 表格的大小可以增长,并且可能每天都在增长。
  • 将一个表拆分成几个表来查看与您谈论 Log(N) 时间时没有任何收获是一样的。因为这基本上就是限制搜索范围时二分搜索所做的。
【解决方案2】:

你能写出这样的哈希函数吗?是的。评估它会比搜索慢吗?那么问题来了……

我会亲自解决这个问题,如下所示。我会有一个所有值的排序向量。然后我会根据n >> 8 的值在该向量中创建一个索引跳转表。

因此,现在您的逻辑是查看跳转表以确定您要跳转到的位置以及您应该考虑多少个值。 (只需查看您着陆的位置与下一个索引的大小,即可查看范围的大小。)如果整个范围都指向同一个向量,那么您就完成了。如果只有几个条目,请进行线性搜索以找到您所属的位置。如果它们有很多条目,请进行二进制搜索。对您的数据进行试验,以找出二分搜索何时胜过线性搜索。

模糊的记忆表明折衷约为 100 左右,因为预测错误的分支代价高昂。但这是多年前的模糊记忆,所以自己进行实验。

【讨论】:

    猜你喜欢
    • 2018-03-23
    • 1970-01-01
    • 2014-05-08
    • 2019-10-30
    • 2019-09-03
    • 2017-03-21
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多