实现查找表

时间:2016-04-05 02:50:58

标签: c++ algorithm indexing lookup lookup-tables

我正在研究自定义数据结构,目前我处于beta测试过程中:数据将存储在一个数组中,此数组可以表示为4D,2D& 1D阵列。这三个数组在union中声明,因为它表示相同的内存寻址。这是我班上的宣言:

SomeClass.h

"accessible_by": { "id": "USER_ID", "type": "user" }

我需要生成这个4D结构的坐标值对的参考查找表来实现它的1D版本。

为了说明索引遍历,您可以参考这些图像以获得直观表示:

3D Visual注意:此图像中的{x,y,z,w}并不代表内存中的实际4D数组:它只是一个可视化!在内存中,4D数组如下:#ifndef SomeClass_H #define SomeClass_H class SomeClass { public: static const unsigned V1D_SIZE; // Single Or Linear Array Representation : Size 256 - 256 Elements static const unsigned V2D_SIZE; // 2D Array [16][16] : Size 16 - 256 Elements static const unsigned V4D_SIZE; // 4D Array [4][4][4][4] : Size 4 - 256 Elements enum Index { HEX_UNDER_FLOW = -0x01, HEX_0 = 0x00, HEX_1 = 0x01, HEX_2 = 0x02, HEX_3 = 0x03, HEX_4 = 0x04, HEX_5 = 0x05, HEX_6 = 0x06, HEX_7 = 0x07, HEX_8 = 0x08, HEX_9 = 0x09, HEX_A = 0x0A, HEX_B = 0x0B, HEX_C = 0x0C, HEX_D = 0x0D, HEX_E = 0x0E, HEX_F = 0x0F, HEX_OVER_FLOW = 0x10 }; // Index // Will Be Private After Testing. union { int m_p256[256]; int m_p16[16][16]; int m_p4[4][4][4][4]; }; private: struct CrossReference { Index A; Index B; CrossReference() {} CrossReference( const Index& A_, const Index& B_ ) : A(A_), B(B_) {} } typedef CR; // Current Not Used Only Here To Illustrate A Simple Representation - May Use Or Incorporate Later struct Cubes { unsigned box; // 0 - 3 - w unsigned slice; // 0 - 15 - z unsigned row; // 0 - 15 - y unsigned coloumn; // 0 - 15 - x } m_cubes; CR m_cr[256]; public: SomeClass(); ~SomeClass(); const CR& getIndexTable() const; void displayIndexTable() const; private: // Must Be Called In Constructor First! void initializeCrossReference(); }; // SomeClass #endif // SomeClass ,此图像代表4D数组中的1个框。

2D Visual 1D LookUp注意:此图像是顶部图像中描述的所有4个框的2D可视化表示。两个图像中的彩色文本对应于适当的索引。

第二图像是该4D阵列数据结构的2D平面网格图像表示。我们可以使用此图像生成此查找表的坐标。

此图片的每个四分之一代表一个方框。左上角(开始)是方框0,右上方框1,左下方框2,右下方框3.每个方框,可以按照相同的方式分解每个切片。左上角(起始)切片0,右上切片1,左下切片2,右下切片3.然后当在每个切片中工作时,遍历为row-col,一旦col = 3,我们向下移动到下一行。因此,在完成单个切片后,我们必须根据当前切片索引跳转我们的位置。盒子也是如此。

以下是遍历此表以生成十六进制表示法的一组索引坐标值的几个示例:

array[box][slice][row][column]

我正在设计一个函数来生成这个查找表。我在这里手动完成了这个:

array[2][3][0][1] our [A,B] hex value would be [0x0C, 0x05] 
array[1][1][3][3] our [A,B] hex value would be [0x03, 0x0F]

正如您所看到的,此功能很长,而且不太可读。我试图找出一种方式以优雅的方式实现这个功能,这就是我被困住的地方。如何使用for循环/ s和几个if语句(如果需要)在几行代码中生成此模式?

最终我想将这些[A,B]坐标压缩成一个无符号字符,好像[A,B] = [0x0C,0x08]它将作为一个字节而不是一对枚举存储为0xC8。

编辑 - 添加一个新图片,该图片应该有助于了解我如何生成我的坐标对以及它们在查找数组中的确切顺序。

Improved Image

注意:这个问题是我接受的帖子,至于这里的旧问题Custom Data Structure: Implementing an algorithim to generate a lookup table [duplicate]现在已经死了,请参考这个是正确的一。昨晚我试图继续编辑旧浏览器时,我的浏览器出现问题。我打算删除它,但我会将其留在那里用于历史目的,并让管理部门决定是否删除它。

3 个答案:

答案 0 :(得分:2)

盯着查找表几分钟(并且只在查找表中的原始数据中,我无法跟踪图形),我相信以下示例将生成您的查找表。 / p>

正如我告诉你in your first question,大部分问题都是无关紧要的。如果你摆脱了问题的前三分之一,有人可能很快会想出答案。有时它确实有助于了解数据意味着什么,但在这里它似乎更多的是分心,而不是其他任何东西。

无论如何,首先要做的是摆脱enum。它没有添加任何价值,只是妨碍了。只需使用自然的十六进制数字即可。话虽如此,使用您自己的代码进行调整应该是微不足道的:

#include <iostream>

int main()
{
    for (int n=0; n<256; ++n)
    {
        int a = ((((n >> 5) & 1) << 2) | (n & 0x80) >> 4) | ((n >> 2) & 3);
        int b = (n & 3) | (((n >> 4) & 1) << 2) |
            (((n >> 6) & 1) << 3);

        std::cout << n << ": a=" << a << " b=" << b << std::endl;
    }
}

我有一种唠叨的感觉,这可以简化得更多一些,也许其他人可以做出改进,但是,无论如何,这个的输出似乎与原始的十六进制值相匹配,对于{{1在您的查找表中。}和A

答案 1 :(得分:1)

例如,像这样:

for (int i = 0; i < 256; ++i) {
    int cube = i / 64;
    int slice = (i % 64) / 16;
    int row = (i % 16) / 4;
    int col = i % 4;
    m_cr[i].A = cube / 2 * 8 + slice / 2 * 4 + row;
    m_cr[i].B = cube % 2 * 8 + slice % 2 * 4 + col;
}

答案 2 :(得分:0)

首先将HEX_更改为数组。然后,查看各个块并将它们转换为循环。由于您的=SUMIF(B1:F1,">="&C7,INDEX(B2:F4,MATCH(C6,A2:A4,0),0)) - SUMIF(B1:F1,">"&C8,INDEX(B2:F4,MATCH(C6,A2:A4,0),0)) .A是互斥的,我们可能会单独处理它们。

这是&#34;功能&#34;您可以用来帮助初始化A:

.B

B的实现非常相似:

void InitializeA(CrossReference arr[])
{
    InitializeABlock(arr, 0x00, 0x00);
    InitializeABlock(arr, 0x10, 0x00);
    InitializeABlock(arr, 0x20, 0x04);
    InitializeABlock(arr, 0x30, 0x04);
    InitializeABlock(arr, 0x40, 0x00);
    InitializeABlock(arr, 0x50, 0x00);
    InitializeABlock(arr, 0x60, 0x04);
    InitializeABlock(arr, 0x70, 0x04);

    InitializeABlock(arr, 0x80, 0x08);
    InitializeABlock(arr, 0x90, 0x08);
    InitializeABlock(arr, 0xA0, 0x10);
    InitializeABlock(arr, 0xB0, 0x10);
    InitializeABlock(arr, 0xC0, 0x08);
    InitializeABlock(arr, 0xD0, 0x08);
    InitializeABlock(arr, 0xE0, 0x10);
    InitializeABlock(arr, 0xF0, 0x10);
}

void InitializeABlock(CrossReference arr[], int idxStart, int hexStart)
{
    for(int j = hexStart; j < hexStart + 4; j++)
    {
        int baseIdx = idxStart + 4 * (j - hexStart);

        for(int i = 0; i < 4; i++)
        {
            arr[baseIdx + i].A = j;
        }
    }
}

当然,您可以进一步压缩这一点。 ;)