繁体   English   中英

从最近的邻居搜索创建邻接矩阵。 (将邻接列表转换为邻接矩阵)-Matlab

[英]Create adjacency matrix from nearest neighbour search. (convert adjacency list to adjacency matrix) - Matlab

我有一个矩阵2000x5 ,在第一列中是点号,在2-5列中是4个邻居(如果没有邻居,则为0)。 有没有一种有效的方法可以据此创建邻接矩阵?

1   129 0   65  0
2   130 0   66  85
3   131 169 67  0
4   132 170 68  87
5   133 0   69  81
6   134 0   70  82
7   135 173 71  83
8   136 174 72  84
9   137 161 73  0
10  138 162 74  93
11  139 163 75  0
12  140 164 76  95
13  141 165 77  89
14  142 166 78  90
15  143 167 79  91
16  144 168 80  92
17  145 0   81  65
18  146 0   82  66
....

我找到了以下线程,仅在一个邻居中对其进行了说明,但是我不确定如何在多个邻居中使用它。 Matlab邻接表到邻接矩阵

非常感谢您的帮助。

首先,我将假定邻接表是无向的 无论如何,去多个邻居并不是一件容易的事。 首先,需要检测第2列至第5列中每行非零元素的总数。执行此操作后,对于邻接矩阵的行,您将复制点数尽可能多的次数每行非零元素。 函数repelem非常适合为您执行此操作。 列索引将只是第二列到第五列, 删除所有零元素。 如何做到这一点的方法是首先对矩阵进行转置 ,从而对第二到第五列进行索引,然后使用logical索引矩阵删除零个条目。 这样做将以列为主的方式展开向量,这就是为什么在执行此操作之前需要转置的原因。 完成此操作后,您可以创建行和列访问索引,以便可以像链接的帖子一样将它们输入到sparse

假设您的矩阵存储在A ,您将执行以下操作。 这也假设连接节点的每个权重为1:

% Find total number of non-zero elements per row, skipping first column
non_zero = sum(A(:,2:end) ~= 0, 2);

% Create row indices
rows = repelem(A(:,1), non_zero);

% Create column indices
cols = A(:,2:end).';    
cols = cols(cols ~= 0);

% Create adjacency matrix
adj = sparse([rows; cols],[cols; rows], 1);

上面的表示是sparse 如果需要完整的数字版本,请使用full强制转换输出:

adj = full(adj);

如果您的图形是有向的

如果您有向图而不是无向图,则上述对sparse副本的调用会复制边,以便您创建往返于每个邻居的链接。 如果您的图形实际上是有向的,则只需要使用行和列索引一次即可,而不必使用上面的代码两次:

% Create adjacency matrix
adj = sparse(rows, cols , 1);

测试用例

这是一个小的测试用例,向您显示此方法有效。 假设我的邻接列表如下所示:

>> A = [1 0 2 3; 2 4 0 0; 3 0 0 4]

A =

     1     0     2     3
     2     4     0     0
     3     0     0     4

现在,邻接矩阵为:

>> full(adj)

ans =

     0     1     1     0
     1     0     0     1
     1     0     0     1
     0     1     1     0

看一下上面的列表以及如何填充矩阵,我们可以验证这是正确的。


关于repelem注意repelem

repelem假定您具有MATLAB R2015a或更高版本。 如果你没有这个,你可以参考此答案由用户Divakar上自定义实现的repelem :此数组元素的重复副本:运行长度解码的MATLAB

快速简单的技术:

adjMat = zeros(size(A,1));
for ind = 1:size(A,1)
    % Flag 1 on each row 'ind' at the indices mentioned in col 2-5
    adjMat(ind, nonzeros(A(ind,2:end))) = 1;
end

既然您已经提到使用最近邻居搜索,那么很可能应该完全填充邻接列表以生成无向图,这意味着如果第1行有20个邻居,那么第20行很可能有1个邻居。

但是,从技术上讲,这将产生一个与邻接表完全等效的邻接矩阵,而无需单独假设。

例:

对于邻接表

A = [1 2 3; 2 0 1; 3 1 4; 4 5 3; 5 4 0]

A =

 1     2     3
 2     0     1
 3     1     4
 4     5     3
 5     4     0

结果是:

adjMat =

 0     1     1     0     0
 1     0     0     0     0
 1     0     0     1     0
 0     0     1     0     1
 0     0     0     1     0

PS要强制方向性,您只需在for循环主体中添加另一个语句:

adjMat(nonzeros(A(ind,2:end)),ind) = 1;

这将确保邻接矩阵是对称的,这是无向图的特征。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM