如何在C++中混合使用数组和映射

How can I use a mixture of array and map in C++?

本文关键字:数组 映射 混合 C++      更新时间:2023-10-16

我的问题的一个简短版本:是否可以使用数组数据结构,例如,将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)x(2*10^12)

我正在用普通数组列出并存储第一个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下的索引作为数组,其余部分作为映射?

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

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

TL;博士

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

理论上,您可以使用ArrayWithHash库来存储字典。它将dictionary存储为数组和哈希表的混合体,类似于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的缺点之一。它将阵列焊成两个大小的幂,所以阵列部分将吃掉1GB。至于哈希表的实现,它的内存效率甚至更低:它可能需要比存储键/值对所需的内存多三倍的内存。