用于索引映射的高效算法

时间:2012-02-24 20:21:26

标签: c++ algorithm

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

  1. 索引的二进制搜索。这具有内存效率,并且具有复杂性O(log n)

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

  3. 对于我的应用程序,内存和速度都很重要。我缺乏记忆,因为这是一个数字运算代码,因此可以使用数亿个点。速度也很重要,因为算法将被多次调用。

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

2 个答案:

答案 0 :(得分:2)

一如既往:个人资料。我们可以猜测,但如果不运行代码,我们可能会错。我做了一个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

因此,正如您所看到的,时间完全取决于您在代码中执行的操作。尝试不同的事情,通过优化时间,并以最快的速度为您的代码服务。

答案 1 :(得分:0)

  

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

std::map<value, value>。或std::unordered_map I.e.任何地图类,双重。 即第一个映射将值从arrayA映射到arrayB,第二个映射将值从arrayB映射到arrayA。或者首先将map映射到value,然后将value映射到index。

您可以使用std::lower_bound(二分搜索)和两个std::vector<std::pair<value, value> >执行相同操作,但您需要确保对所有数据进行排序。它会比两个std::map使用更少的内存,但是你很可能会花更多的时间来确保数据的排序。

  

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

  1. 你忘记了开发时间。如果您的完美解决方案需要3个月的时间,那么可能不值得。
  2. 您需要知道自己拥有多少内存,使用的数据类型以及预期的数据量。
  3. 总有平衡。无论是“速度”还是“记忆”。或者是中间的东西。
  4.   

    数亿点

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