如何存储对称矩阵?

时间:2010-07-06 15:58:26

标签: language-agnostic matrix

哪种方法是在内存中存储对称矩阵?

在不降低结构速度和复杂性的情况下节省一半空间将是一件好事。这是一个与语言无关的问题,但是如果你需要做一些假设,只要假设它是一个很好的旧的简单编程语言,如C或C ++ ..

似乎有一种感觉就是如果有一种方法可以保持简单或只是当矩阵本身非常大时,我是对的吗?

仅仅为了形式,我的意思是这个断言对于我想要存储的数据总是如此

matrix[x][y] == matrix[y][x]

6 个答案:

答案 0 :(得分:17)

这是存储对称矩阵的好方法,它只需要N(N + 1)/ 2个内存:

int fromMatrixToVector(int i, int j, int N)
{
   if (i <= j)
      return i * N - (i - 1) * i / 2 + j - i;
   else
      return j * N - (j - 1) * j / 2 + i - j;
}

对于某些三角矩阵

0 1 2 3
  4 5 6
    7 8
      9

1D表示(例如,存储在std::vector中)如下所示:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

来自MatrixToVector(1,2,4)的调用返回5,因此矩阵数据是vector [5] - &gt; 5。

有关详细信息,请参阅http://www.codeguru.com/cpp/cpp/algorithms/general/article.php/c11211/TIP-Half-Size-Triangular-Matrix.htm

答案 1 :(得分:6)

我发现许多高性能软件包只存储整个矩阵,但只读取上三角形或下三角形。然后,他们可能会在计算过程中使用额外的空间来存储临时数据。

但是,如果存储确实存在问题,那么只需将n(n+1)/2元素存储为一维数组中的上三角形。如果这使得访问变得复杂,只需定义一组辅助函数。

在C中访问矩阵matA,您可以定义一个宏:

#define A(i,j, dim) ((i <= j)?matA[i*dim + j]:matA[j*dim + i])

然后您几乎可以正常访问您的阵列。

答案 2 :(得分:1)

好吧,我会尝试三角形矩阵,如下:

int[][] sym = new int[rows][];
for( int i = 0; i < cols; ++i ) {  
     sym=new int[i+1];
}

但是当有人想要访问“另一方”时,你将不得不面对这个问题。例如,他想要访问[0] [10],但在你的情况下,这个val存储在[10] [0]中(假设为10x10)。

可能“最好”的方式是懒惰的方式 - 在用户请求之前不要做任何事情。因此,如果用户输入类似print(matrix [4])的某些内容,则可以加载特定行。

答案 3 :(得分:1)

如果你想使用一维数组,代码看起来像这样:

int[] new matrix[(rows * (rows + 1 )) >> 1];
int z;
matrix[ ( ( z = ( x < y ? y : x ) ) * ( z + 1 ) >> 1 ) + ( y < x ? y : x ) ] = yourValue; 

如果您创建一个额外的查找表,则可以摆脱乘法运算:

int[] new matrix[(rows * (rows + 1 )) >> 1];
int[] lookup[rows];
for ( int i= 0; i < rows; i++)
{
   lookup[i] = (i * (i+1)) >> 1;
}
matrix[ lookup[ x < y ? y : x ] + ( x < y ? x : y )  ] = yourValue;

答案 4 :(得分:0)

如果你正在使用支持运算符重载的东西(例如C ++),那么透明地处理它很容易。只需创建一个检查两个下标的矩阵类,如果第二个大于第一个,则交换它们:

template <class T>
class sym_matrix { 
    std::vector<std::vector<T> > data;
public:
    T operator()(int x, int y) {
        if (y>x)
            return data[y][x];
        else
            return data[x][y];
    }
};

目前我已经跳过其他所有内容,只是覆盖了下标。实际上,要正确使用左值和右值,您通常需要直接返回代理而不是T。你需要一个创建data作为三角形的ctor(即,对于NxN矩阵,第一行将具有N个元素,第二行将具有N-1,依此类推,或者等效地为1,2, ... N)。您也可以考虑将data创建为单个vector - 您必须计算其中的正确偏移量,但这并不是非常困难,并且它将使用更少的内存,运行速度更快,我会使用第一个版本的简单代码,并在必要时进行优化。

答案 5 :(得分:0)

如果您的语言支持,您可以使用交错数组(或任何它们被称为),当x&lt; y,切换x和y的位置。所以......

对于n x n矩阵的伪代码(有点Python样式,但不是真的):

matrix[n][]

for i from 0 to n-1:
    matrix[i] = some_value_type[i + 1]

[next, assign values to the elements of the half-matrix]

然后提到价值......

if x < y:
    return matrix[y][x]
else:
    return matrix[x][y]