9

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

0 1 2

3 4 5

6 7 8

在这种情况下,很容易获得 i,j 坐标(n 是矩阵维度)。对于基于 0 的索引,它会是。

i = 索引 / n

j = 索引 % n

现在,如果我的矩阵是对称的,我只想访问上部怎么办

0 1 2 3

.. 4 5 6

..... 7 8

........... 9

我知道线性指数将由

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

但我想知道给定 idx 的 i,j。你们知道这样做的任何方法吗?我在这里查找了这个,但我找不到答案。提前致谢。

4

8 回答 8

10

如果你想使用你使用的索引,并且你想避免循环,你可以反转索引的函数。我将使用 k 来表示线性索引,并且所有索引都是从零开始的。正如你所指出的

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

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

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

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

行 = 分钟 { 我 | k - ni + i(i-1)/2 >= 0 }。

如果你求解二次方程 k - ni + i(i-1)/2 = 0 并取 i 的底,这会给你行,即

行 = 楼层( (2n+1 - sqrt( (2n+1)^2 - 8k ) ) / 2 )

然后

j = k - 行 * n + 行 * (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 ;

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

于 2013-10-02T18:48:51.207 回答
4

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

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

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

于 2013-10-02T18:51:47.390 回答
2

这是对 Keeran Brabazon 回答的评论。k = j + n i - i (i-1) /2 - 这是您帖子中的等式,它是错误的,正确的等式是 k = j + (2*n -1 -i)*i/2。但是我们不能用它来寻找 i。

您帖子中的方程式可用于查找 i(行索引),但我们无法将 i 代入您的方程式并得到 j,因此您帖子中 j 的公式是错误的,因此最终结果将如下所示:

i = floor( ( 2*n+1 - sqrt( (2n+1)*(2n+1) - 8*k ) ) / 2 ) ;(和你的完全一样)

j = k - (2*n-1- i)*i/2; (与您的版本不同,我通过将 i 代入我的等式来得到它)

于 2017-06-15T10:26:58.107 回答
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,所以它只是伪代码,但它应该可以工作。正如 horchler 所说,确保您的索引是正确的。我i,j在这里使用了您在示例中使用的方法,但对我来说感觉很奇怪

于 2013-10-02T18:30:03.360 回答
0

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

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

return i, j;
于 2013-10-02T18:47:56.197 回答
0

对于基于 0 索引:

int j = 0;
int x = (n-1);
while (idx > x) {
    j++;
    idx=idx-x;
    x--;
}
i=idx;
于 2014-05-16T20:58:05.177 回答
0

MATLAB 附带内置函数 ind2sub 和 sub2ind。请查看 MATLAB 的文档。

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

示例:对于 3 x 3 矩阵

1 4 7

2 5 8

3 6 9

于 2019-02-18T17:14:59.983 回答
0

你可以用这个

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

这是对马特答案的更新。B,因为您想要逐行表示。

于 2016-09-23T09:53:50.357 回答