C++ 如何将M维数组转换为N维数组?

C++ 如何将M维数组转换为N维数组?,c++,arrays,algorithm,templates,multidimensional-array,C++,Arrays,Algorithm,Templates,Multidimensional Array,受到arr2D[i][j]和arr1D[i*k+j]的启发,在阅读了相关内容及其下面的注释后,我想知道一种可以更改任何数组维数的算法 让我试着把它形式化: 输入: 一个M多维容器A 容器的尺寸D(尺寸) 目标维度N 输出: 如果N>0则返回与A内容相同的N维容器B,否则返回错误代码 注意: 您可以为N维容器选择任何最佳大小 编辑: 我不需要任何完全工作的代码。我在问是否有任何算法可以做到这一点?将[100]转换为[10][10]: #include <iostream> typed

受到
arr2D[i][j]
arr1D[i*k+j]
的启发,在阅读了相关内容及其下面的注释后,我想知道一种可以更改任何数组维数的算法

让我试着把它形式化:

输入:

  • 一个
    M
    多维容器
    A

  • 容器的尺寸
    D
    (尺寸)

  • 目标维度
    N

  • 输出:

    如果
    N>0
    则返回与
    A
    内容相同的N维容器
    B
    ,否则返回错误代码

    注意:

    您可以为N维容器选择任何最佳大小

    编辑:


    我不需要任何完全工作的代码。我在问是否有任何算法可以做到这一点?

    将[100]转换为[10][10]:

    #include <iostream>
    
    typedef int (*parray)[10];
    
    parray foo (int *in) {
        return (parray)in;
    }
    
    int main()
    {
        int in[100];
        in[55] = 42;
        int (*out)[10] = foo(in);
        std::cout << out[5][5] << std::endl;
    
        return 0;
    }
    
    #包括
    typedef int(*parray)[10];
    帕雷福(整数*整数){
    返回(帕雷)在;
    }
    int main()
    {
    int in[100];
    in[55]=42;
    int(*out)[10]=foo(in);
    
    std::cout您的原始
    M
    -多维容器是
    A

    我们想创建一个新的
    N
    多维容器
    B
    ,它将保存
    a
    的所有内容

    首先,我们必须找出一个映射,我们可以在
    a
    B
    中轻松找到相同的元素

    让我们使用一些示例来推断映射是如何实现的:

    (1)M=2,N=1

    A: a * b    B: c
    we can set the dimension c to be a * b, thus we have
    A[i][j] = B[i * c + j]
    
    (2)M=3,N=1

    A: a * b * c    B: d
    d = a * b * c
    A[i][j][k] = B[(i * b * c) + (j * c) + k]
    
    (3)M=3,N=2

    A: a * b * c    B: d * e
    d = a, e = b * c
    A[i][j][k] = B[i][j * c + k]
    
    (4)M=4,N=1

    A: a * b * c * d    B: e
    e = a * b * c * d
    A[i][j][k][l] = B[(i * b * c * d) + (j * c * d) + (k * d) + l]
    
    (5)M=5,N=4

    A: a * b * c * d * e    B: u * v * w * x
    u = a, v = b, w = c, x = d * e
    A[i][j][k][l][m] = B[i][j][k][(l * e) + m]
    
    (6)M=5,N=2

    A: a * b * c * d * e    B: f * g
    f = a, g = b * c * d * e
    A[i][j][k][l][m] = B[i][(j * c * d * e) + (k * d * e) + (l * e) + m]
    

    如果A有M个维度a1,a2,…,aM,B有N个维度b1,b2,…,bN,我们可以说:

    如果M>N,则对于所有0 这样我们就知道了如何创建B以及B的每个维度的大小

    使用示例中所示的映射功能,您可以轻松地将任何
    M
    -维度矩阵转换为
    N
    -维度矩阵


    如果
    M
    ,您可以做相同的事情,但方向相反。

    因为您不需要代码,让我解释一下如何使用模板来完成

    假设你有一个大小为n{0},…,n{D-1}的D维数组,你总是可以通过将其中两个数组的大小相乘来删除一个维度。例如:a[5][4][3]包含60个元素,因此b[20][3]或c[5][12](对于简单的情况,因为你甚至可以构造D[15][4]和任何置换)可以很容易地包含与a相同的元素,索引的映射也很明显

    现在使用C++做它更复杂,但你需要:可变模板和模板元编程。
    变量模板用于定义任意维的数组类型,模板元编程用于定义将D维数组映射到N维数组的运算符。(我可以说这并不容易,但却是模板元编程中一个非常困难的好练习).

    因此,您只需在不更改任何数据的情况下重新格式化矩阵。正如我在评论中所暗示的,最简单的方法是使用1D数组中间步骤将M维转换为N维

    这里的其他答案都在同一条轨道上,但缺乏完整的数学知识……它们只是一些小维度的例子,没有通用方程,所以这里是:

    要在
    A[A0][A1]…[A(M-1)]
    X[A0*A1*…*A(M-1)]
    之间转换,其中
    A0,A1,….A(M-1)
    是容器的尺寸(分辨率),只需执行以下操作:

    // M-D -> 1D
    x = a0
       +a1*A0
       +a2*A0*A1
       ...
       +a(M-1)*A0*A1*...*A(M-2);
    
    // 1D -> M-D   
    q=x;
    a0 = q%A0; q/=A0;
    a1 = q%A1; q/=A1;
    a2 = q%A2; q/=A2;
    ...
    a(M-1) = q%A(M-1); q/=A(M-1);
    
    其中
    a0,a1,…a(M-1)
    x
    是数组中的索引

    实际上,您不需要将M-D数组转换为1D,然后再转换回N-D,只需转换索引即可:

    for(a0=0;a0
    

    我认为这类似于将数字表示从一个基数转换为另一个基数。每个维度的唯一区别是基数不同。例如,您可以将十进制数字1234视为四维数组中的索引,其中每个维度的大小为10。要显示任何代码吗?显示您迄今为止尝试过的内容。出于实际目的,只需模板包装器对线性<代码> STD::向量<代码>提供X维访问应该足够,只有当向量的大小必须不同时,该问题是什么。@ AdtEngDeCuffi在C++中添加了答案……至少打破了严格的混叠规则,所以UB。我仍然无法理解这一点,也许是Type和函数。你能解释一下吗?正如@Jarod指出的,你不想这样做,除非是作为一个练习。它是使用强制转换将100个整数从100x1重新映射到10x10。数组只是隐藏在引擎盖下的地址算术。哦,我明白了@stark谢谢。你知道这个问题为什么会有反对票吗?不知道。我有点惊讶我没有投反对票等等,如果M有k个因子,N>k怎么办?M[a][b]可以简单地投影到M[1][1][a][b],不是吗?是的@jean baptisteyunès。我一直在寻找一种最佳的方法。你展示了一个微不足道的解决方案,但我想知道这是否也是最佳的解决方案?你所说的最佳是什么意思?最后,机器中的一切都是平的,因此这只是一个利用坐标索引线性结构的问题。哦@jean baptisteyunès,我没有想一想。我会对你的回答投赞成票。如果M有k个因子,N>k呢?因子你指的是维度?在我的回答中,已经有了解释。如果
    M
    的维度小于
    N
    ,你只需在相反的方向做同样的事情。这种方法对任何一角都是最佳的
    M
    N
    .ig的扩展,所以我不能完全理解它,因为格式和一些精简的解释添加了一些示例,希望如此
    A0*A1*...*A(M-1) <= B0*B1*...*B(N-1)