我想在数组中存储一个对称矩阵
对于一个矩阵我是这样做的
double[,] mat = new double[size,size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j <= i; j++)
mat[i, j] = mat[j, i] = (n * other_matrix[i,j]);
}
如果我想存储在一个数组中
double[] mat = new double[size*size];
代替
double[,] mat
什么是最有效的方法?
使用 mat[i*n+j]
?
最佳答案
是的。
按行存储元素,其中i
第 - 行和 j
-th 列存储在索引 k=i*NC+j
中与 NC
列数。这适用于非对称一般矩阵。
存储大小为 N
的对称矩阵你只需要 N*(N+1)/2
数组中的元素。您可以假设 i<=j
这样数组索引就像这样:
k(i,j) = i*N-i*(i+1)/2+j i<=j //above the diagonal
k(i,j) = j*N-j*(j+1)/2+i i>j //below the diagonal
与
i = 0 .. N-1
j = 0 .. N-1
例子当N=5时,数组索引是这样的
| 0 1 2 3 4 |
| |
| 1 5 6 7 8 |
| |
| 2 6 9 10 11 |
| |
| 3 7 10 12 13 |
| |
| 4 8 11 13 14 |
所需的元素总数为 5*(5+1)/2 = 15
因此索引来自 0..14
.
i
-th 对角线有索引 k(i,i) = i*(N+1)-i*(i+1)/2
.所以第 3 行 ( i=2
) 有对角索引 k(2,2) = 2*(5+1)-2*(2+1)/2 = 9
.
i
的最后一个元素-th 行的索引 = k(i,N) = N*(i+1)-i*(i+1)/2-1
.所以第 3 行的最后一个元素是 k(2,4) = 5*(2+1)-2*(2+1)/2-1 = 11
.
您可能需要的最后一部分是如何从数组索引 k
开始到行i
和列 j
.再次假设i<=j
(在对角线上)答案是
i(k) = (int)Math.Floor(N+0.5-Math.Sqrt(N*(N+1)-2*k+0.25))
j(k) = k + i*(i+1)/2-N*i
为了检查上面的内容,我为 N=5
运行了这个, k=0..14
得到如下结果:
这是正确的!
要制作副本,只需使用 Array.Copy()
在超快的元素上。此外,要执行加法和缩放等操作,您只需处理数组中减少的元素,而不是完整的 N*N
。矩阵。矩阵乘法有点棘手,但可行。如果你愿意,也许你可以为此问另一个问题。
关于c# - 在 C# 中高效地复制对称矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9039189/