javascript对链接节点进行分组

javascript对链接节点进行分组,javascript,arrays,list,d3.js,grouping,Javascript,Arrays,List,D3.js,Grouping,我有两个列表-节点和链接。。。现在我想要的是最有效的方法,将所有直接/间接链接的元素添加到不同的组中。。。。例如,0连接到1,1连接到2,因此节点0,1,2成为组1。。。。节点3连接到4,因此它成为组2,依此类推。。。。提前感谢您的帮助:)这是d3实现的一部分 PS:这些列表将很容易包含在成千上万个节点和链接中 "nodes":[ { "id":0, "x":1509.9862, "y":-609.1013 }, { "id":1

我有两个列表-节点和链接。。。现在我想要的是最有效的方法,将所有直接/间接链接的元素添加到不同的组中。。。。例如,0连接到1,1连接到2,因此节点0,1,2成为组1。。。。节点3连接到4,因此它成为组2,依此类推。。。。提前感谢您的帮助:)这是d3实现的一部分

PS:这些列表将很容易包含在成千上万个节点和链接中

"nodes":[
   {
      "id":0,
      "x":1509.9862,
      "y":-609.1013
   },
   {
      "id":1,
      "x":1645.9578,
      "y":-85.06705
   },
   {
      "id":2,
      "x":1948.1533,
      "y":-469.3646
   },
   {
      "id":3,
      "x":348.1533,
      "y":-669.3646
   },
   {
      "id":4,
      "x":1448.1533,
      "y":-1469.3646
   }
   ...
  ]

  "links":[
     {
        "from":0,
        "to":1
     },
     {
        "from":1,
        "to":2
     },
     {
        "from":3,
        "to":4
     }
     ...
  ]  

这是一个典型的UnionFind问题。其思想是将每个节点视为一个集合,其中有一个指向其父节点的指针。具有相同父节点的节点位于同一组中。因此,对于您的问题,我们可以在开始时创建n个集合。然后遍历链接,将通过同一链接连接的所有人分组。复杂度为O(n),其中n是节点数

节点=[{
“id”:0,
“x”:1509.9862,
“y”:-609.1013
},
{
“id”:1,
“x”:1645.9578,
“y”:-85.06705
},
{
“id”:2,
“x”:1948.1533,
“y”:-469.3646
},
{
“id”:3,
“x”:348.1533,
“y”:-669.3646
},
{
“id”:4,
“x”:1448.1533,
“y”:-1469.3646
}
];
链接=[{
“from”:0,
“至”:1
},
{
“从”:1,
“至”:2
},
{
“从”:3,
“至”:4
}
];
//联合查找是一种数据结构,可以合并两个集合并进行检查
//两个元素是否在同一集合中。
var-father={};
功能组(节点、链接){
//创建n个集合,每个集合都将节点作为其唯一元素
forEach(函数(node,i){
父节点[node.id]=node.id;
});
//联合每个在它们之间有链接的集合
links.forEach(函数(link,i){
联合(link.from,link.to);
});
//对于每个联合集,将节点分组在一起
var-id=1;
var groupIdCnt={};
var groupIds={};
forEach(函数(node,i){
var f=查找(node.id);
if(groupId的类型[f]=“未定义”){
groupIds[f]=id;
groupIdCnt[id]=1;
id++;
}否则{
groupIdCnt[groupIds[f]]++;
}
});
变量组={};
forEach(函数(node,i){
var f=查找(node.id);
if(groupIdCnt[groupIds[f]]==1){
节点['group']=0;
}否则{
节点['group']=groupIds[f];
}
if(组的类型[节点['group']]=='undefined'){
组[节点['group']]=[];
}
组[node['group']]。推送(node);
});
返回Object.value(组);
}
//找到每一组的父亲
函数查找(节点){
//如果它是根,则返回
if(父[节点]==节点){
返回节点;
}
//如果没有,找到父亲并指向他
父[节点]=查找(父[节点]);
返回父节点;
}
//将包含节点1的集合的父集合更新为包含节点2的集合的父集合
功能联合(节点1、节点2){
父亲[find(node1)]=find(node2);
}
//O(n),因为我们访问每个节点一次
变量组=组(节点、链接);
console.log(节点);

控制台日志(组)这是一个典型的UnionFind问题。其思想是将每个节点视为一个集合,其中有一个指向其父节点的指针。具有相同父节点的节点位于同一组中。因此,对于您的问题,我们可以在开始时创建n个集合。然后遍历链接,将通过同一链接连接的所有人分组。复杂度为O(n),其中n是节点数

节点=[{
“id”:0,
“x”:1509.9862,
“y”:-609.1013
},
{
“id”:1,
“x”:1645.9578,
“y”:-85.06705
},
{
“id”:2,
“x”:1948.1533,
“y”:-469.3646
},
{
“id”:3,
“x”:348.1533,
“y”:-669.3646
},
{
“id”:4,
“x”:1448.1533,
“y”:-1469.3646
}
];
链接=[{
“from”:0,
“至”:1
},
{
“从”:1,
“至”:2
},
{
“从”:3,
“至”:4
}
];
//联合查找是一种数据结构,可以合并两个集合并进行检查
//两个元素是否在同一集合中。
var-father={};
功能组(节点、链接){
//创建n个集合,每个集合都将节点作为其唯一元素
forEach(函数(node,i){
父节点[node.id]=node.id;
});
//联合每个在它们之间有链接的集合
links.forEach(函数(link,i){
联合(link.from,link.to);
});
//对于每个联合集,将节点分组在一起
var-id=1;
var groupIdCnt={};
var groupIds={};
forEach(函数(node,i){
var f=查找(node.id);
if(groupId的类型[f]=“未定义”){
groupIds[f]=id;
groupIdCnt[id]=1;
id++;
}否则{
groupIdCnt[groupIds[f]]++;
}
});
变量组={};
forEach(函数(node,i){
var f=查找(node.id);
if(groupIdCnt[groupIds[f]]==1){
节点['group']=0;
}否则{
节点['group']=groupIds[f];
}
if(组的类型[节点['group']]=='undefined'){
组[节点['group']]=[];
}
组[node['group']]。推送(node);
});
返回Object.value(组);
}
//找到每一组的父亲
函数查找(节点){
//如果它是根,则返回
if(父[节点]==节点){
返回节点;
}
//如果没有,找到父亲并指向他
父[节点]=查找(父[节点]);
返回父节点;
}
//将包含节点1的集合的父集合更新为包含节点2的集合的父集合
功能联合(节点1、节点2){
父亲[find(node1)]=find(node2);
}
//O(n),因为我们访问每个节点一次
变量组=组(节点、链接);
console.log(节点);

控制台日志(组)在下面的解决方案中,我正在创建一组相互链接的
链接。我这样做是通过循环查看从
/
组合的所有
,并找出其中一个是否已添加到
链接的任何累积组中。如果有,那么我只需将
from
to
值添加(或重新添加)到该组。如果
from
to
值均未分组,则我将创建一个新组,并将
from
添加到