【问题标题】:Efficient algorithm for index mapping索引映射的高效算法
【发布时间】:2012-02-24 20:21:26
【问题描述】:

假设您遇到以下问题。您有两个具有一对一映射的索引集。为简单起见,假设您有一个类似 int a [] = {21, 30, 45, 78} 的数组,此列表将 {1, 2, 3, 4} 映射到 {21, 30, 45, 78}。获得反向映射的最有效方法是什么,即给定索引30,您希望算法为45 返回2,您希望3 等等。我可以想到以下几点:

  1. 对索引进行二分搜索。这是内存效率高且具有复杂性O(log n)

  2. 拥有一个包含79 元素和reverseMap[21] = 1, reverseMap[30] = 2, reverseMap[45] = 3, reverseMap[78] = 4 的数组。这是O(1),因此速度更快,但内存效率不高。

对于我的应用程序来说,内存和速度都很重要。我内存不足,因为这是一个数字运算代码,因此可以处理数亿个点。速度也很重要,因为算法会被多次调用。

我觉得哈希表在这里很有用,但我不太了解它可以发表评论。我很感激对这个问题的任何见解。此外,由于编码是在c++ 中完成的,我希望看到使用STL 而不是外部库的方法。

【问题讨论】:

  • 那我相信你在找codereview.stackexchange.com
  • 我知道您请求了内部库,但值得研究 boost bimap。 boost.org/doc/libs/1_42_0/libs/bimap/doc/html/index.html
  • 哈希是标准的:std::unordered_map,O(1)-ish,而且内存开销要低得多。
  • @GradGuy:如果向量未排序,则不能使用二分搜索作为反向查找,您必须使用线性搜索,或者坚持一个排序的版本。
  • @GradGuy:如果您的数组需要快速查找“数以亿计的点”,那么您将需要换一种思路,因为这些数据无法有效地放入内存中。如果这是针对用户程序的,您可能需要重新设计。

标签: c++ algorithm


【解决方案1】:

一如既往:简介。我们可以猜测,但如果不运行您的代码,我们可能会错。我做了一个rough benchmark on ideone(时间以我的电脑为准)。我在包含一千万个元素的数组中对 unsigned int 进行了十万次查找(我厌倦了等待您的“数亿”),这些是我的结果:

unsorted vector  found 1633382974 in 2140 ticks.
sorted vector  found 1633382974 in 62 ticks.
unordered_map  found 1633382974 in 16 ticks.
std::map  found 1633382974 in 172 ticks. //that's half the time of a blink

但是我必须注意,在程序的内存中维护这些将比未排序的向量产生一些开销。如果我们将创建时间添加到十万次查找的时间中,我们得到:

unsorted vector  found 1633382974 in 2141 ticks.
sorted vector  found 1633382974 in 1797 ticks.
unordered_map  found 1633382974 in 16218 ticks.
std::map  found 1633382974 in 30749 ticks. //a full thirty seconds

因此,如您所见,时间安排完全取决于您在代码中所做的工作。尝试不同的事情,对它们进行优化,然后为您的代码选择最快的。

【讨论】:

  • 我会的。感谢您的有益讨论:)
【解决方案2】:

获取反向映射最有效的方法是什么

std::map<value, value>。或std::unordered_map 即任何地图类,双。 IE。第一个映射将值从arrayA 映射到arrayB,第二个映射将值从arrayB 映射到arrayA。或者第一个映射将索引映射到值,第二个映射将值映射到索引。

您可以使用std::lower_bound(二进制搜索)和两个std::vector<std::pair<value, value> > 来做同样的事情,但您需要确保所有数据都已排序。它将使用比两个 std::maps 更少的内存,但您很可能会花费更多时间来确保对数据进行排序。

对于我的应用程序来说,内存和速度都很重要

  1. 您忘记了开发时间。如果你的完美解决方案需要 3 个月的时间来制作,那可能不值得。
  2. 您需要说明您有多少内存、您使用的数据类型以及预期的数据量。
  3. 总有平衡。 “速度”或“记忆”。或者中间的东西。

数亿点

切换到 64 位,购买额外的内存。或者将排序的数据存储在磁盘上(允许对部分加载的数据进行二进制搜索)并忘记速度,或者尝试使用“从标准输入读取,立即写入标准输出”方式以某种方式处理它。请注意,硬件比开发时间便宜。在不知道您的数据类型的情况下,无法推荐其他任何内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 2023-01-19
    • 1970-01-01
    • 2015-01-18
    • 2011-02-13
    相关资源
    最近更新 更多