javascript – 查找无向图的所有连接组件

我有一个对象列表(无向边),如下所示:
pairs = [

 pair:["a2","a5"],pair:["a3","a6"],pair:["a4",pair:["a7","a9"]

];

我需要在不同的组中找到所有组件(连接的节点).所以从给定的对中我需要得到:

groups = [
  group1: ["a2","a5","a4"],group2: ["a3",group3: ["a7","a9"]
];

我实际上在这里阅读了一些答案并用Google搜索,这就是我学习它的方法,称为“在图中查找连接的组件”,但是找不到任何示例代码.我在Node.js上使用JavaScript,但任何其他语言的样本都会非常有用.谢谢.

解决方法

这可以使用广度优先搜索解决.

我们的想法是通过跳转到相邻的顶点来遍历源顶点的所有可到达顶点.首先访问源顶点旁边的顶点,然后是2跳的顶点,等等.

由于使用了图表表示,这里的代码效率不高,这是一个边缘列表.要获得更好的性能,您可能需要使用邻接列表.

这是JavaScript中的一些工作代码.我使用node.js来运行它:

// Breadth First Search function
// v is the source vertex
// all_pairs is the input array,which contains length 2 arrays
// visited is a dictionary for keeping track of whether a node is visited
var bfs = function(v,all_pairs,visited) {
  var q = [];
  var current_group = [];
  var i,nextVertex,pair;
  var length_all_pairs = all_pairs.length;
  q.push(v);
  while (q.length > 0) {
    v = q.shift();
    if (!visited[v]) {
      visited[v] = true;
      current_group.push(v);
      // go through the input array to find vertices that are
      // directly adjacent to the current vertex,and put them
      // onto the queue
      for (i = 0; i < length_all_pairs; i += 1) {
        pair = all_pairs[i];
        if (pair[0] === v && !visited[pair[1]]) {
          q.push(pair[1]);
        } else if (pair[1] === v && !visited[pair[0]]) {
          q.push(pair[0]);
        }
      }
    }
  }
  // return everything in the current "group"
  return current_group;
};

var pairs = [
  ["a2",["a3",["a4",["a7","a9"]
];

var groups = [];
var i,k,length,u,v,src,current_pair;
var visited = {};

// main loop - find any unvisited vertex from the input array and
// treat it as the source,then perform a breadth first search from
// it. All vertices visited from this search belong to the same group
for (i = 0,length = pairs.length; i < length; i += 1) {
  current_pair = pairs[i];
  u = current_pair[0];
  v = current_pair[1];
  src = null;
  if (!visited[u]) {
    src = u;
  } else if (!visited[v]) {
    src = v;
  }
  if (src) {
    // there is an unvisited vertex in this pair.
    // perform a breadth first search,and push the resulting
    // group onto the list of all groups
    groups.push(bfs(src,pairs,visited));
  }
}

// show groups
console.log(groups);

更新:我已更新我的答案,演示如何将边缘列表转换为邻接列表.代码评论,应该很好地说明这个概念.修改宽度优先搜索功能以使用邻接列表,以及另一个略微修改(关于将顶点标记为已访问).

// Converts an edgelist to an adjacency list representation
// In this program,we use a dictionary as an adjacency list,// where each key is a vertex,and each value is a list of all
// vertices adjacent to that vertex
var convert_edgelist_to_adjlist = function(edgelist) {
  var adjlist = {};
  var i,len,pair,v;
  for (i = 0,len = edgelist.length; i < len; i += 1) {
    pair = edgelist[i];
    u = pair[0];
    v = pair[1];
    if (adjlist[u]) {
      // append vertex v to edgelist of vertex u
      adjlist[u].push(v);
    } else {
      // vertex u is not in adjlist,create new adjacency list for it
      adjlist[u] = [v];
    }
    if (adjlist[v]) {
      adjlist[v].push(u);
    } else {
      adjlist[v] = [u];
    }
  }
  return adjlist;
};

// Breadth First Search using adjacency list
var bfs = function(v,adjlist,adjV,nextVertex;
  q.push(v);
  visited[v] = true;
  while (q.length > 0) {
    v = q.shift();
    current_group.push(v);
    // Go through adjacency list of vertex v,and push any unvisited
    // vertex onto the queue.
    // This is more efficient than our earlier approach of going
    // through an edge list.
    adjV = adjlist[v];
    for (i = 0,len = adjV.length; i < len; i += 1) {
      nextVertex = adjV[i];
      if (!visited[nextVertex]) {
        q.push(nextVertex);
        visited[nextVertex] = true;
      }
    }
  }
  return current_group;
};

var pairs = [
  ["a2","a9"]
];

var groups = [];
var visited = {};
var v;

// this should look like:
// {
//   "a2": ["a5"],//   "a3": ["a6"],//   "a4": ["a5"],//   "a5": ["a2",//   "a6": ["a3"],//   "a7": ["a9"],//   "a9": ["a7"]
// }
var adjlist = convert_edgelist_to_adjlist(pairs);

for (v in adjlist) {
  if (adjlist.hasOwnProperty(v) && !visited[v]) {
    groups.push(bfs(v,visited));
  }
}

console.log(groups);

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...