对称矩阵中的线性索引

时间:2013-10-02 18:02:35

标签: c++ algorithm matlab matrix

我们可以使用线性索引访问矩阵,该索引遵循此模式

0 1 2

3 4 5

6 7 8

这种情况很容易得到i,j坐标(n是矩阵维度)。对于0指数,它将是。

i = index / n

j = index%n

现在,如果我的矩阵是对称的,我只想访问上半部分

0 1 2 3

.. 4 5 6

..... 7 8

........ 9

我知道线性索引将由

给出

index = j + n * i - i(i-1)/ 2

但我想知道我,j给出了idx。你们知道这样做的任何方式吗?我在这里查了一下,但我找不到答案。提前谢谢。

8 个答案:

答案 0 :(得分:8)

如果要使用您使用的索引,并且希望避免循环,则可以反转索引功能。我将使用k来表示线性索引,并且所有索引都是基于零的。正如你所说的那样

k = j + n * i - i *(i-1)/ 2。

看到我们正在使用正整数,并且所有组合(i,j)映射到不同的k意味着该函数是可逆的。我这样做的方法首先要注意

j = k - n * i + i *(i-1)/ 2

这样,如果您可以找到您所在的行,则该列由上面的等式定义。现在考虑你想要的行,它被定义为

row = min {i | k-ni + i(i-1)/ 2> = 0}。

如果求解二次方程k - ni + i(i-1)/ 2 = 0并取i的最低值,则会给出行,即

row = floor((2n + 1 - sqrt((2n + 1)^ 2 - 8k))/ 2)

然后

j = k - row * n + row *(row-1)/ 2。

在伪代码中,这将是

//Given linear index k, and n the size of nxn matrix
i = floor( ( 2*n+1 - sqrt( (2n+1)*(2n+1) - 8*k ) ) / 2 ) ;
j = k - n*i + i*(i-1)/2 ;

这消除了对循环的需要,并且对于大型矩阵来说会更快

答案 1 :(得分:4)

由于还没有人发布过Matlab解决方案,这里有一个简单的单行程序:

idxs = find(triu(true(size(A))))

给定矩阵A,这将返回所有索引的向量,这样idxs(k)将第k个线性索引返回到矩阵的上三角部分。

答案 2 :(得分:2)

This is comment to Keeran Brabazon answer. k = j + ni - i(i-1) /2 - this is equation from your post and it's wrong, the correct equation is k = j + (2*n -1 -i)*i/2. But we can't use it for finding i.

Equation from your post could be used to find i(row index), but we can't substitue i into your equation and get j, therefore formula for j in your post is wrong, so the final result will be looks like this:

i = floor( ( 2*n+1 - sqrt( (2n+1)*(2n+1) - 8*k ) ) / 2 ) ;(exactly like yours)

j = k - (2*n-1- i)*i/2; (different from your version, and i'm getting it by substituting i into my equation)

答案 3 :(得分:1)

循环遍历您的行,跟踪每个行的偏移量以及每个行的起始索引:

offset = 0;
startOfRow = 0;
for(i=0;i<height;i++){
    endOfRow = startOfRow + (width - offset);
    if(idx < endOfRow){ 
        j = (idx - endOfRow) + width;
        return {i,j};
    } else {                           
        startOfRow = endOfRow;
        offset++;
    }
}

我不知道Matlab,所以它只是伪代码,但它应该有效。正如霍克勒所说,确保你的索引是正确的。我在你的示例中使用了i,j,但它只是感觉很奇怪

答案 4 :(得分:0)

这是我能想到的最简单的方法:

int i = 1, j, x=n;
while (idx > x)
{
    i++;
    idx=idx-x;
    x--;
}
j=idx+(i-1);

return i, j;

答案 5 :(得分:0)

基于0指数:

int j = 0;
int x = (n-1);
while (idx > x) {
    j++;
    idx=idx-x;
    x--;
}
i=idx;

答案 6 :(得分:0)

您可以使用此

idxs = find(triu(true(size(A)))');

这是Matt答案的更新。 B,因为你想要逐行表示。

答案 7 :(得分:0)

MATLAB附带了内置函数ind2sub和sub2ind。请检查MATLAB文档。

请注意,在MATLAB中,线性索引沿行向下,索引从1开始

示例:对于3 x 3矩阵

1 4 7

2 5 8

3 6 9