可以相互连接的节点的高效分组

时间:2013-03-15 00:34:56

标签: javascript jquery algorithm d3.js underscore.js

我有一些图表数据,其中节点之间的边缘在这个表格上:

var edges = [
    ["A","B"], ["B","C"], ["B","D"], ["E","F"], ["E","G"]
];

对可以互相访问的节点进行分组的最有效(运行时)方法是什么?就我而言:

[["A","B","C","D"],["E","F","G"]]

我正在寻找纯JavaScript的解决方案,或者可能使用d3.js,underscore.js或jQuery。伪代码也很好:)


更新:因为有些人认为这是this question的副本,我会解释我使用它的原因。

我有许多2D点(可能少于500点),我想组合彼此接近的点。首先我在delaunay triangulation获得平面图,我在边上添加euclidean distance作为权重,然后使用Kruskal's algorithm制作minimum spanning tree(MST)。我从MST中移除所有长边的边。现在我最终得到了许多边缘(如上所述),我想要处理并找到集群。当我拥有星团时,我会制作它们的凸包,以便将其可视化。

所以这是一个无向图。边缘告诉我的唯一事情是它连接的两个顶点将在同一个集群中。

即使点数可能很低,运行时间也很重要,因为这将在每次鼠标移动时计算。


解决方案:感谢您的建议。为了完整起见,我提出了解决方案:

// Make a cluster for each vertex
var clusters = _.map(vertices, function(node) { return [node]; });

while(edges.length > 0) {

    var edge = edges.pop();
    var vertexA = edge[0],
        vertexB = edge[1];

    var cA = _.filter(clusters, function(cluster) {
        return _.contains(cluster, vertexA);
    });

    var cB = _.filter(clusters, function(cluster) {
        return _.contains(cluster, vertexB);
    });

    if(_.union(_.difference(cA,cB) , _.difference(cB,cA) ).length > 0) {
        clusters = _.without(clusters, cA[0], cB[0]);
        clusters.push(_.union(cA[0], cB[0]));
    }
}

return clusters;

2 个答案:

答案 0 :(得分:0)

这就是我要做的事情:

  1. 制作节点列表。将每个标记为未访问(白色)
  2. 从第一个节点开始将其标记为灰色。只处理breadth-firstdepth first search处理白色节点。当您与父母结束时,将其标记为黑色。
  3. 列表中的所有黑色节点都已连接。您可以从(1)中创建的列表中删除它们,然后再次执行此操作以查找下一组连接节点。

答案 1 :(得分:0)

这是有向图吗?或无向图?

如果是无向图,您可以使用bfs / dfs。

  1. 浏览未访问的顶点列表。
  2. 从具有边缘且尚未访问的另一个顶点的顶点开始。做bfs / dfs。跟踪当前遍历中正在访问的节点
  3. 将您在当前遍历中访问过的节点分组。
  4. 转到1.
  5. 复杂性与BFS / DFS相同。