2

当使用一个奇数的立方 3d 数组(3x3x3、5x5x5、7x7x7 等)时,返回该数组的 2d 切片的最有效方法是什么,给定切片的方向轴和一个值用于确定切片沿该轴的相关位置?

4

2 回答 2

1

由于这对我来说是一个非常有趣的话题,所以我也一直在寻找答案。我认为您可能对Mark Byers的方法感到幸运:

Mark 没有将其存储在 3D 数组中,而是在如何使用 1D 数组方面提供了一种非常好的方法。

经过一番尝试,我想出了完整的立方体,希望这适合你:

public class Cube {
    int w, h, d;
    int[] cube;

    public Cube(int w, int h, int d) {
        this.w = w;
        this.h = h;
        this.d = d;
        System.out.println("cube: w" + w + ", h" + h + ", d" + d + " = " + (w * h * d));
        cube = new int[w * h * d];
    }

    int getCubeValue(int x, int y, int z) {
        return cube[x * h * d + y * d + z];
    }

    void setCubeValue(int x, int y, int z, int value) {
        System.out.println("value " + (x * h * d + y * d + z) + ": x" + x + ", y" + y + ", z" + z + " = " + value);
        cube[x * h * d + y * d + z] = value;
    }

    int[] xSlice(int x) {
        int[] slice = new int[h * d];
        for(int y = 0; y < h; y++) {
                for(int z = 0; z < d; z++) {
                        slice[y * d + z] = getCubeValue(x, y, z);
                }
        }
        return slice;
    }

    int xSliceValue(int[] slice, int y, int z) {
        return slice[y * d + z];
    }

    int[] ySlice(int y) {
        int[] slice = new int[d * w];
        for(int z = 0; z < d; z++) {
                for(int x = 0; x < w; x++) {
                        slice[z * w + x] = getCubeValue(x, y, z);
                }
        }
        return slice;
    }

    int ySliceValue(int[] slice, int x, int z) {
        return slice[z * w + x];
    }

    int[] zSlice(int z) {
        int[] slice = new int[w * h];
        for(int x = 0; x < w; x++) {
            for(int y = 0; y < h; y++) {
                slice[x * h + y] = getCubeValue(x, y, z);
            }
        }
        return slice;
    }

    int zSliceValue(int[] slice, int x, int y) {
        return slice[x * h + y];
    }
}

假设你像这样制作一个 Cube new Cube(3, 3, 3),最后一个值将是可接近的,cube.getCubeValue(2, 2, 2)因为它从零开始。

于 2013-04-14T08:52:05.783 回答
1

我认为您可以选择三个选项,具体取决于您希望切片方法的输入和输出是什么:

  • 切片作用于原始多维 Java 数组,生成原始多维 Java 数组,例如:

int[][] ArrayUtils.slice(int[][][] cube, int axis, int sliceIndex)

  • 切片适用于原始多维 Java 数组,生成带有 getter 的对象,例如:

SomeKindOf2DimArrayClass ArrayUtils.slice(int[][][] cube, int axis, int sliceIndex)

  • 切片使用非原始数组作为输入和输出,并且是此类的一种方法:

SomeKindOf2DimArrayClass slice(int axis, int sliceIndex)

就您的界面而言。

实现方面,如果您使用原始数组,那么您别无选择,只能做一些“繁重的工作”——为 siice 构建一个二维数组——至少为第三轴。对于第一个轴,您只需使用 2d 数组中的一个(即result = Arrays.copyOf(cube[sliceIndex]),如果您感觉活泼,甚至可以使用参考);对于第二个轴,你会有类似的东西

for(int i=0; i<cube.length; i++) {
    myAllocated2dArray[i] = Arrays.copyOf(cube[i][sliceindex])
}

如果您使用的是一个对象,那么您有很多选择,从我刚才描述的内容到@Aquillo 在他的回答中建议的内容,再到使用 getter 方法的原始数组的 O(1) 空间包装器。

通过阅读C 语言常见问题解答中有关类似问题的答案,您可能会获得关于已经建议的两种实现的一些灵感,其中明确使用指针(引用):

将静态和动态分配的多维数组传递给函数时,如何交替使用它们?

于 2013-04-14T14:00:59.417 回答