在阅读this post及其下的注释后,受到arr2D[i][j]
和arr1D[i * k + j]
的启发,我想知道一种可以更改任何数组维数的算法。
让我尝试对其进行形式化:
输入:
一个M
维的容器A
容器的尺寸D
(尺寸)
目标尺寸N
输出:
如果N > 0
,则返回内容与B
相同的N维容器A
,否则返回错误代码。
注意:
您可以为N维容器选择任何最佳尺寸。
编辑:
我不需要任何能正常工作的代码。我问是否有任何算法可以做到这一点?
答案 0 :(得分:1)
将[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;
}
答案 1 :(得分:1)
您原来的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及其每个尺寸的大小。
使用示例中显示的映射功能,您可以轻松地将任何M
维矩阵转换为N
维矩阵。
如果使用M < N
,您可以做相反的事情。
答案 2 :(得分:1)
因为您不需要代码,所以让我解释一下如何使用模板。
假设您有一个尺寸为n_ {0},...,n_ {d-1}的D维数组,则始终可以通过将两个维数相乘来删除一个维。示例:a [5] [4] [3]包含60个元素,因此b [20] [3]或c [5] [12](在简单情况下,因为您甚至可以构造d [15] [4]和任何排列)都可以轻松地包含与a相同的元素,索引的映射也是如此明显...
现在使用C ++进行操作更加棘手,但是您将需要:可变参数模板和模板元编程。
可变参数模板用于定义您喜欢的任何维的数组类型,模板元编程用于定义将D维数组映射到N维数组的运算符。 (我可能会说这并不容易,但是在模板元编程中是非常困难的练习。)
答案 3 :(得分:1)
因此,您只想在不更改数据的情况下重新格式化矩阵。正如我在评论中所暗示的那样,最简单的方法是使用中间一维数组将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<A0;a0++)
for (a1=0;a1<A1;a1++)
...
for (a(M-1)=0;a(M-1)<A(M-1);a(M-1)++)
{
// M-D -> 1D
x = a0
+a1*A0
+a2*A0*A1
...
+a(M-1)*A0*A1*...*A(M-2);
// 1D -> N-D
q=x;
b0 = q%B0; q/=B0;
b1 = q%B1; q/=B1;
b2 = q%B2; q/=B2;
...
b(N-1) = q%B(N-1); q/=B(N-1);
// copy A -> B
B[b0][b1]...[b(N-1)] = A[A0][A1]...[A(M-1)];
}
不要忘记尺寸必须为:
A0*A1*...*A(M-1) <= B0*B1*...*B(N-1)
否则,您将无法访问数组,因为A
中的数据将不适合B
。
如果您具有动态尺寸,可以使用: