Algorithm 用相邻单元的平均值替换矩阵中的每个单元

Algorithm 用相邻单元的平均值替换矩阵中的每个单元,algorithm,matrix,Algorithm,Matrix,要求:必须在适当的地方完成 例如: 给定矩阵 1, 2, 3 4, 5, 6 7, 8, 9 应替换为其3*3个相邻单元和自身单元之和的平均值: (1+2+4+5)/4, (2+1+3+4+5+6)/6 , (3+2+6+5)/4 (1+2+5+4+7+8)/6, (1+2+3+4+5+6+7+8+9)/9, (2+3+5+6+8+9)/6 (4+5+7+8)/4, (4+5+6+7+8+9)/6, (5+6

要求:必须在适当的地方完成

例如:

给定矩阵

1, 2, 3
4, 5, 6
7, 8, 9
应替换为其3*3个相邻单元和自身单元之和的平均值:

(1+2+4+5)/4,       (2+1+3+4+5+6)/6 ,            (3+2+6+5)/4
(1+2+5+4+7+8)/6,   (1+2+3+4+5+6+7+8+9)/9,       (2+3+5+6+8+9)/6
(4+5+7+8)/4,       (4+5+6+7+8+9)/6,             (5+6+8+9)/4
即:

All floating number convert to int

3,      3.5(3), 4             3, 3, 4
4.5(4),  5, 5.5(5)  =>        4, 5, 5
6,      6.5(6), 7             6, 6, 7
我试图迭代矩阵并更新每个单元格,但我发现这会影响未来的计算:

假设我将原始1更新为3,但当我尝试更新原始2时,原始1现在变为3


复制原始矩阵来计算平均值是一个解决办法,但这不是一个好主意,我们能在不占用那么多空间的情况下实现吗

在大多数情况下,您只需创建原始矩阵的副本,并将其用于计算平均值。除非创建矩阵副本会使用比可用内存更多的内存,否则开销应该可以忽略不计

如果您有一个非常大的矩阵,您可以使用“滚动”备份(没有更好的术语)。假设您逐行更新单元格,并且当前位于第n行。您不需要备份第n-2行,因为这些单元格不再相关,第n+1行也不相关,因为它们仍然是原始值。因此,您可以只保留上一行和当前行的备份。每当前进到下一行时,放弃上一行的备份,将当前行的备份移动到上一行,并创建新的当前行的备份

一些伪代码(不考虑任何边缘情况):


(您还可以保留下一行的备份,这样您就可以对所有值只使用备份行,而不必进行区分。)

在大多数情况下,您应该创建原始矩阵的副本,并使用该副本计算平均值。除非创建矩阵副本会使用比可用内存更多的内存,否则开销应该可以忽略不计

如果您有一个非常大的矩阵,您可以使用“滚动”备份(没有更好的术语)。假设您逐行更新单元格,并且当前位于第n行。您不需要备份第n-2行,因为这些单元格不再相关,第n+1行也不相关,因为它们仍然是原始值。因此,您可以只保留上一行和当前行的备份。每当前进到下一行时,放弃上一行的备份,将当前行的备份移动到上一行,并创建新的当前行的备份

一些伪代码(不考虑任何边缘情况):


(您还可以保留下一行的备份,这样您就可以对所有值仅使用备份行,而不必区分。)

您必须对结果数据进行某种缓存,以便保留对原始数据的引用。我认为没有办法解决这个问题

如果数据集很大,可以通过使用较小的数据缓冲区(如通过锁孔查看)并在更新时“滚动”输入矩阵来进行优化。在您的情况下,可以使用小到3x3的缓冲区。 不过,这是速度和空间之间的折衷。缓冲区越小,性能就越差

要可视化问题,请从数据集的左上角(0,0)开始:
(为简单起见,结果值向下舍入)

第一步:更新前4个单元格(初始化缓冲区)

然后对于每个迭代..
(用[xx]表示的新值)

++从结果集中更新数据集中的第一列

// Data Set        // Data Viewport   // Result Set
[04],02,03,04,05   01,02,03         04,04,??
[06],07,08,09,10   06,07,08         06,07,??
 11 ,12,13,14,15   11,12,13         ??,??,??
 16 ,17,18,19,20
 21 ,22,23,24,25
++将数据视口和结果集右移1列

// Data Set        // Data Viewport // Result Set
[04],02,03,04,05   02,03,04         04,[03],??
[06],07,08,09,10   07,08,09         07,[08],??
 11 ,12,13,14,15   12,13,14         ??, ?? ,??
 16 ,17,18,19,20
 21 ,22,23,24,25
++更新结果集的中间列

// Data Set        // Data Viewport // Result Set
[04],02,03,04,05   02,03,04         04,[05],??
[06],07,08,09,10   07,08,09         07,[08],??
 11 ,12,13,14,15   12,13,14         ??, ?? ,??
 16 ,17,18,19,20
 21 ,22,23,24,25
在以下迭代中,数据状态将为:

// Data Set        // Data Viewport // Result Set
04,[04],03,04,05   03,04,05         05,[06],??
06,[07],08,09,10   08,09,10         08,[09],??
11, 12 ,13,14,15   13,14,15         ??, ?? ,??
16, 17 ,18,19,20
21, 22 ,23,24,25
。。等

别忘了处理其他边缘情况


*“数据”视口表示仅用于可视化。在代码中,实际的视口将是结果缓冲区。

必须对结果数据进行某种缓存,以便保留对原始数据的引用。我认为没有办法解决这个问题

如果数据集很大,可以通过使用较小的数据缓冲区(如通过锁孔查看)并在更新时“滚动”输入矩阵来进行优化。在您的情况下,可以使用小到3x3的缓冲区。 不过,这是速度和空间之间的折衷。缓冲区越小,性能就越差

要可视化问题,请从数据集的左上角(0,0)开始:
(为简单起见,结果值向下舍入)

第一步:更新前4个单元格(初始化缓冲区)

然后对于每个迭代..
(用[xx]表示的新值)

++从结果集中更新数据集中的第一列

// Data Set        // Data Viewport   // Result Set
[04],02,03,04,05   01,02,03         04,04,??
[06],07,08,09,10   06,07,08         06,07,??
 11 ,12,13,14,15   11,12,13         ??,??,??
 16 ,17,18,19,20
 21 ,22,23,24,25
++将数据视口和结果集右移1列

// Data Set        // Data Viewport // Result Set
[04],02,03,04,05   02,03,04         04,[03],??
[06],07,08,09,10   07,08,09         07,[08],??
 11 ,12,13,14,15   12,13,14         ??, ?? ,??
 16 ,17,18,19,20
 21 ,22,23,24,25
++更新结果集的中间列

// Data Set        // Data Viewport // Result Set
[04],02,03,04,05   02,03,04         04,[05],??
[06],07,08,09,10   07,08,09         07,[08],??
 11 ,12,13,14,15   12,13,14         ??, ?? ,??
 16 ,17,18,19,20
 21 ,22,23,24,25
在以下迭代中,数据状态将为:

// Data Set        // Data Viewport // Result Set
04,[04],03,04,05   03,04,05         05,[06],??
06,[07],08,09,10   08,09,10         08,[09],??
11, 12 ,13,14,15   13,14,15         ??, ?? ,??
16, 17 ,18,19,20
21, 22 ,23,24,25
。。等

别忘了处理其他边缘情况


*“数据”视口表示仅用于可视化。在代码中,实际视口将是结果缓冲区。

通常的方法是在更新单元格之前创建矩阵副本。如果矩阵非常非常大,您可以只保留一个“滚动”备份,例如上一行和当前行,甚至更少。假设您有一个1000x1000矩阵,并且您正在逐行更新单元格。在第n行中,您不需要第n-2行的副本(因为它不再相关),也不需要第n+1行的副本(因为它仍然具有原始值。因此仅保留上一行和当前行的备份就足够了。是否值得这样做是另一个问题。@tobias_k您能解释一下“滚动”的细节吗详细备份?我认为这可能是关键。在更新单元格之前创建矩阵副本是常用的方法。如果矩阵非常非常大,您可以进行“滚动”备份,例如上一行和当前行,甚至更少。假设您有一个1000x1000矩阵,并且您正在逐行更新单元格