索引映射的有效算法

Efficient algorithm for index mapping

本文关键字:算法 有效 映射 索引      更新时间:2023-10-16

假设您遇到以下问题。您有两个具有一对一映射的索引集。为了简单起见,假设您有一个类似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而不是外部库的方法。

一如既往:PROFILE。我们可以猜测,但如果不运行您的代码,我们可能会错。我在ideone上做了一个粗略的基准(时间是基于我的电脑)。我在一个有1000万个元素的数组中对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

因此,正如您所看到的,时间完全取决于您在代码中所做的操作。尝试不同的东西,在上进行优化,并以最快的速度运行代码。

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

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

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

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

  1. 您忘记了开发时间。如果你的完美解决方案需要3个月的时间来制作,那么它可能不值得
  2. 你需要知道你有多少内存,你使用什么样的数据,以及期望有多少数据
  3. 总是有平衡的。要么是"速度",要么是"内存"。或者在中间的东西

数亿点

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