将二维数组转换为一维数组并不难,但如何将超过二维的多维数组转换为一维数组呢?例如,假设我有 int [5][5][5] x 和 int [125] y,并且我想将 x[3][4][2] 的值放在 y 中的正确位置上,应该怎么做呢?
希望这样说得清楚了。
将二维数组转换为一维数组并不难,但如何将超过二维的多维数组转换为一维数组呢?例如,假设我有 int [5][5][5] x 和 int [125] y,并且我想将 x[3][4][2] 的值放在 y 中的正确位置上,应该怎么做呢?
希望这样说得清楚了。
好的,所以你知道如何从一维情况转到二维情况。
一个一维数组看起来像这样:
int [5] :
+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | 3 | 4 |
| | | | | |
+-----+-----+-----+-----+-----+
一个二维数组看起来像这样:
int [5][5] :
+-----+-----+-----+-----+-----+
| 0,0 | 0,1 | 0,2 | 0,3 | 0,4 |
| | | | | |
+-----+-----+-----+-----+-----+
| 1,0 | 1,1 | 1,2 | 1,3 | 1,4 |
| | | | | |
+-----+-----+-----+-----+-----+
| 2,0 | 2,1 | 2,2 | 2,3 | 2,4 |
| | | | | |
+-----+-----+-----+-----+-----+
| 3,0 | 3,1 | 3,2 | 3,3 | 3,4 |
| | | | | |
+-----+-----+-----+-----+-----+
| 4,0 | 4,1 | 4,2 | 4,3 | 4,4 |
| | | | | |
+-----+-----+-----+-----+-----+
你可以将转换为相应的一维数组想象成这样:
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+- - -
| 0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 1,0 | 1,1 | 1,2 | 1,3 | 1,4 | etc.
| | | | | | | | | | |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+- - -
vvv
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+- - -
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | etc.
| | | | | | | | | | |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+- - -
但是另一种思考方式是将原始数组重新标记,就像这样:
int [5][5] :
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
| 0,0 | 0,1 | 0,2 | 0,3 | 0,4 | | 0 | 1 | 2 | 3 | 4 |
| | | | | | | | | | | |
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
| 1,0 | 1,1 | 1,2 | 1,3 | 1,4 | | 5 | 6 | 7 | 8 | 9 |
| | | | | | | | | | | |
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
| 2,0 | 2,1 | 2,2 | 2,3 | 2,4 | => | 10 | 11 | 12 | 13 | 14 |
| | | | | | | | | | | |
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
| 3,0 | 3,1 | 3,2 | 3,3 | 3,4 | | 15 | 16 | 17 | 18 | 19 |
| | | | | | | | | | | |
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
| 4,0 | 4,1 | 4,2 | 4,3 | 4,4 | | 20 | 21 | 22 | 23 | 24 |
| | | | | | | | | | | |
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
2-D array index [i][j] => 1-D array index [i*5 + j]
......如果你这样考虑,三维情况只是遵循同样的原则(对于更高的维度也是如此——只是越来越难以可视化!):
int [5][5][5] :
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
|+-----+-----+-----+-----+-----+ |+-----+-----+-----+-----+-----+
||+-----+-----+-----+-----+-----+ ||+-----+-----+-----+-----+-----+
|||+-----+-----+-----+-----+-----+ |||+-----+-----+-----+-----+-----+
||||1,0,0|1,0,1|1,0,2|1,0,3|1,0,4| |||| 25 | 26 | 27 | 28 | 29 |
|||| +-----+-----+-----+-----+-----+ |||| +-----+-----+-----+-----+-----+
|||+---|0,0,0|0,0,1|0,0,2|0,0,3|0,0,4| |||+---| 0 | 1 | 2 | 3 | 4 |
||||1,1| | | | | | |||| 30| | | | | |
|||| +-----+-----+-----+-----+-----+ |||| +-----+-----+-----+-----+-----+
|||+---|0,1,0|0,1,1|0,1,2|0,1,3|0,1,4| |||+---| 5 | 6 | 7 | 8 | 9 |
||||1,2| | | | | | |||| 35| | | | | |
|||| +-----+-----+-----+-----+-----+ |||| +-----+-----+-----+-----+-----+
|||+---|0,2,0|0,2,1|0,2,2|0,2,3|0,2,4|=>|||+---| 10 | 11 | 12 | 13 | 14 |
||||1,3| | | | | | |||| 40| | | | | |
|||| +-----+-----+-----+-----+-----+ |||| +-----+-----+-----+-----+-----+
+||+---|0,3,0|0,3,1|0,3,2|0,3,3|0,3,4| +||+---| 15 | 16 | 17 | 18 | 19 |
+||1,4| | | | | | +|| 45| | | | | |
+| +-----+-----+-----+-----+-----+ +| +-----+-----+-----+-----+-----+
+---|0,4,0|0,4,1|0,4,2|0,4,3|0,4,4| +---| 20 | 21 | 22 | 23 | 24 |
| | | | | | | | | | | |
+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+
3-D array index [i][j][k] => 1-D array index [i*5*5 + j*5 + k]
m0,m1,.. are dimensions
A(i,j,k,...) -> A0[i + j*m0 + k*m0*m1 + ...]
一个有用的C语言技巧:
double *A;
size_t m;
#define A(i,j) A[(i) + (j)*m];
您可以有不同的方法将多维数组映射到线性数组中。关键是您必须选择一种约定。让我们采用以下约定。第一个索引指定块容器,第二个指定先前容器中的块,最后第三个索引是块内的偏移量。您可以轻松地将其推广到多维度,但让我们在此示例中保持为3:
#include <cstddef>
std::size_t linear_index
(std::size_t f,
std::size_t s,
std::size_t t,
std::size_t f_width,
std::size_t s_width)
{
return (f*f_width + s)*s_width + t;
}
public class ArrayIndexer
{
private readonly int[] _bounds;
private readonly int[] _sum;
public ArrayIndexer(params int[] bounds)
{
_bounds = bounds;
// Pre-compute bounds sums for speed.
_sum = new int[bounds.Length - 1];
for (int i = 1, sum = _bounds[i - 1]; i < _bounds.Length; ++i, sum *= _bounds[i - 1])
_sum[i-1] = sum;
}
public T Index<T>(T[] array, params int[] indices)
{
if (indices.Length != _bounds.Length)
throw new ArgumentException("There should be as many indices as bounds", "indices");
var index = indices[0];
for (int i = 1, sum = _bounds[i - 1]; i < indices.Length; ++i, sum *= _bounds[i - 1])
index += sum * indices[i];
return array[index];
}
public T FastIndex<T>(T[] array, params int[] indices)
{
if (indices.Length != _bounds.Length)
throw new ArgumentException("There should be as many indices as bounds", "indices");
var index = indices[0];
for (int i = 1; i < indices.Length; ++i)
index += _sum[i-1] * indices[i];
return array[index];
}
}
或将其转换为 n 维数组。
public static class ArrayExtensions
{
public static Array CreateArray<T>(this T[] array1d, params int[] bounds)
{
var arrayNd = Array.CreateInstance(typeof(T), bounds);
var indices = new int[bounds.Length];
for (var i = 0; i < array1d.Length; ++i)
{
arrayNd.SetValue(array1d[i], indices);
for (int j = 0; j < bounds.Length; ++j)
{
if (++indices[j] < bounds[j])
break;
indices[j] = 0;
}
}
return arrayNd;
}
}
并进行测试。
int[] array3d =
new[]
{
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
16, 17, 18, 19,
20, 21, 22, 23
};
var copied3d = (int[, ,])array3d.CreateArray(4, 3, 2);
var indexer3d = new ArrayIndexer(4, 3, 2);
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 3; ++j)
{
for (int k = 0; k < 2; ++k)
{
var x = indexer3d.FastIndex(array3d, i, j, k);
var y = copied3d[i, j, k];
Debug.Print("Array[{0},{1},{2}] = {3} and {4} match = {5}", i, j, k, x, y, x == y);
}
}
}