使用数组实现Matrix构造时哪个更有效? 使用1D数组还是数组数组(2D)?
我认为2D更有效,因为你已经拥有元素的X和Y坐标,在1D实现中你必须计算索引。
编辑:它正在使用Java实现
答案 0 :(得分:12)
“高效”并不是一个包罗万象的术语。
阵列阵列解决方案在存储方面更有效,其中阵列可能是稀疏的(即,您可以使用空指针来表示所有零的矩阵线)。这将是(在C中):
int *x[9];
其中每个"int *"
将单独分配。
2D数组(不一定是数组数组)通常会更快(在速度方面有效),因为它使用数学计算出内存位置,而不必取消引用内存位置。我在谈论这个结构:
int x[9][9];
形式的一维数组:
int x[81];
不可能比等效的2D版本更快,因为你仍然需要在某些时候进行计算以找到正确的单元格(在代码中手动而不是让编译器这样做)。
编辑后添加Java作为要求:
我相信Java 2D数组是多种数组的数组(这将需要两次内存访问,而不是一维数组所需的内存访问),因此具有手动索引计算的一维数组可能会更快。所以,而不是声明和使用:
int x[width][height];
x[a][b] = 2;
你可以通过以下方式获得更快的速度:
int x[width*height];
x[a*height+b] = 2;
你只需要小心,不要将公式混淆在任何地方(即,不要无意中交换4和7)。
这种速度差异是基于我认为Java在封面下编码的方式所以我可能是错的(但我怀疑它:-)。我的建议是,与优化问题一样,测量,不要猜测!
答案 1 :(得分:3)
我将使用迄今为止的答案打破排名并提出以下原因,即一维数组可能更快。
2D阵列涉及2次内存访问。例如,[x] [y]首先必须查找A [x],然后再查找该数组[y]。
传统上,1D实现将是A [x +(width * y)]。当宽度在寄存器(或文字)中时,这意味着2个数学运算和1个查找而不是2个查找。查找比数学操作慢几个数量级,因此如果宽度在寄存器中即使是一小部分时间,或者是文字,它也会更快。
当然标准警告适用。始终进行分析,避免过早优化。
答案 2 :(得分:2)
我不认为这个问题可以在没有实际编写示例代码和测试结果的情况下得到解答。例如,this question找到了以下结果。
sum(double[], int): 2738 ms (100%)
sum(double[,]): 5019 ms (183%)
sum(double[][]): 2540 ms ( 93%)
锯齿状数组最快,其次是1维数组,其次是多维数组。最快的锯齿状阵列可能不是人们所预测的。这些结果可能对Java无用,因为Java有不同的优化(并且Java中没有多维数组)。
我会非常小心地做出假设。例如,如果你循环遍历2D数组的一行,Java可能会优化索引查找或超出范围检查它可能不是如果您正在使用具有内联索引计算的一维数组。
我建议编写一个简单的程序来测试所需平台的速度。
答案 3 :(得分:1)
根据语言的不同,没有区别。真正的问题是如何分配2D矩阵。它是X * Y字节的单个连续空间,还是分配为X大小的Y独立数组。后者通常在创建稀疏矩阵时完成。
答案 4 :(得分:0)
我在职业生涯中用作机械工程师的商业有限元软件包,使用一维数组作为线性代数计算的基础。有限元方法导致大,稀疏和带状的基质。将所有这些零元素存储在乐队之外是没有意义的。
你唯一能看到二维数组使用的是小型学术问题或非稀疏问题(例如边界元素方法)。
答案 5 :(得分:0)
在一般情况下,任何算法的最有效实现是具有最少代码量的算法。这有很多原因:
这也取决于访问模式。你总是走遍整个矩阵吗?稀疏吗?您更喜欢处理行还是列?
在极端情况下(具有十亿行和一列且仅使用10个单元的矩阵),HashMap
可以比任何阵列实现更有效。对于其他问题,根据问题混合方法可能更有效(例如,当一个巨大的空白区域中的单元“聚集”时,迷你矩阵数组为HashMap
。
如果您的问题要求找到行/列然后处理这些值,那么使用2D方法可能更有效,因此第一次访问会返回一个数组,然后您可以在不打扰边界的情况下处理该数组,一次性 - 错误等