【问题标题】:How can I use a mixture of array and map in C++?如何在 C++ 中混合使用数组和映射?
【发布时间】:2015-05-08 01:27:46
【问题描述】:

我的问题的简短版本:是否可以使用数组数据结构,例如,将x[0]x[10] 视为普通数组,而将其他一些点值x[15]x[20] 视为一张地图? 原因:我不计算或存储任何其他大于索引 11 的值, 并将整个事物制作成地图会显着减慢计算速度。

我最初的问题:我正在编写一个快速程序来计算一个系列,它有x(0)=0x(1)=1x(2k)=(3x(k)+2x(Floor(k/2)))mod2^60x(2k+1)=(2x(k)+3x(Floor(k/2)))mod2^60,我的目标是列出从x(10^12) 到@987654330 的数字@

我正在使用普通数组列出并存储第一个 10^8 值,

for (unsigned long long int i = 2; i<=100000000;i++){
    if (i%2==0) {
        x[i] =(3*x[i/2] + 2*x[(unsigned long long int)(i/4)])&1152921504606846975;
    }
    else{
        x[i] =(2*x[(i-1)/2] + 3*x[(unsigned long long int)((i-1)/4)])&1152921504606846975;
    }

 }//these code for listing
unsigned long long int xtrans(unsigned long long int k){
    if (k<=100000000)return x[k];
    unsigned long long int result;
    if (k%2==0) {
        result =(3*xtrans(k/2) + 2*xtrans((unsigned long long int)(k/4)))&1152921504606846975;
    }
    else{
        result =(2*xtrans((k-1)/2) + 3*xtrans((unsigned long long int)((k-1)/4)))&1152921504606846975;
    }
    return result;
}//These code for calculating x

列出这些数字需要大约 2 秒和 750MB 的内存。

我计划存储特定值,例如x[2*10^8]x[4*10^8],而不计算和存储其他值以进行进一步优化。但是在这种情况下我必须使用地图。但是,在我将 x 的声明从数组转换为映射后,我花了 90 年代和 4.5GB 内存来实现相同的列表。 所以我现在想知道是否可以将10^8以下的索引用作数组,其余部分用作map?

【问题讨论】:

  • 您可以使用成对的向量实现映射,该向量按成对的第一个值(键)进行排序,并在向量上使用std::lower_bound 等。与法线贴图相比,这有一些优点/缺点,但对于较小的 n 可能更快。 boost 中可能已经有一个平面图结构。
  • 我的简单解决方案是编写一个新类,它同时包含一个大数组和一个地图。如果要查找或存储的索引小于数组的大小,请使用数组。否则,请使用地图。
  • 你有没有考虑把整个事情变成unordered_map?如果您不需要按排序顺序检索地图中的项目,unordered_map 往往会给您更好的性能。
  • 我相信你必须写 1152921504606846975ULL 而不是 1152921504606846975 以避免不断溢出,所以也许你当前的代码不能像你期望的那样工作。

标签: c++ arrays optimization dictionary


【解决方案1】:

只需为您的想法编写一个包装器class

class MyMap {
    ...
    operator[](size_t i) {
        return ( i <= barrier_ ) ? array_[i] : map_[i];
    }
}

【讨论】:

    【解决方案2】:

    TL;DR

    为什么不使用大小为 10 的 std::arraystd::map 作为成员创建自定义类,并覆盖 [] 运算符以检查索引并根据需要从数组或映射中选择值。

    【讨论】:

      【解决方案3】:

      理论上,您可以使用ArrayWithHash 库来存储您的字典。它将字典存储为数组和哈希表的混合体,类似于 lua 解释器中的表实现。

      Awh::ArrayWithHash<uint64_t, uint64_t> x;
      dict.Reserve(100000000, 0);   //preallocate array part
      for (uint64_t i = 2; i <= 100000000; i++) {
          if (i % 2 == 0) {
              x.Set(i, (3 * x.Get(i/2) + 2 * x.Get(i/4)) & 1152921504606846975ULL);
          }
          ...
      

      不幸的是,内存消耗是 ArrayWithHash 的缺点之一。它将数组填充为 2 的幂大小,因此数组部分会占用 1 GB。至于哈希表的实现,它的内存效率甚至更低:它可能需要比存储键/值对所需的内存多三倍。

      【讨论】:

        猜你喜欢
        • 2017-10-13
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-28
        • 2012-10-06
        相关资源
        最近更新 更多