【问题标题】:How can I build a graph from a 2D array?如何从二维数组构建图形?
【发布时间】:2013-12-05 01:31:34
【问题描述】:

我正在尝试学习图形结构和算法。从概念上讲,我了解 DFS、BFS,并且我可以通过提供图形来实现它们,但是传统上的图形是如何组成的?

通常我将它们视为以边为指针的节点列表、带有它们连接的节点的边列表或二维矩阵,其中 arr[node_a][node_b] 的交点是边的权重。

当涉及到根据输入实际构建它时,我不知道从哪里开始。

作为一个例子,当你提供一个二维网格时,你将如何构建一个图形,比如(一个在线 pacman 问题),其中 P 是源节点,-'s 是树中的节点。

%%%%%%%%%%%%%%%%%%%%
%--------------%---%
%-%%-%%-%%-%%-%%-%-%
%--------P-------%-%
%%%%%%%%%%%%%%%%%%-%
%.-----------------%
%%%%%%%%%%%%%%%%%%%%

或者,如果提供邻接列表,您将如何构建它?

我知道这可能是一个大问题,因为这个主题相当复杂。文档链接不胜感激!我一直无法从入门级别找到任何内容。

【问题讨论】:

  • 实际上,如果你得到了那个网格,为什么要制作一个图表?您可以将网格用作隐式图形,对吗?
  • @harold 我该怎么做?

标签: arrays algorithm graph


【解决方案1】:

为此,我编写了这个 javascript,它将一个矩阵(数组的数组)转换为一个无权图。它开始在 4 个方向(上/下/右/左)上导航,而无需走到它已经去的地方。

然后,它会使用 DFS 找到最短路径。

const wall = 0
const flat = 1
const target = 9

// no diagonals
const possibleMoves = [
  [-1, 0], // nord
  [0, +1],
  [+1, 0], // sud
  [0, -1],
]

function pathFinder(map) {
  const gridW = map[0].length
  const gridH = map.length
  const start = buildNode([0, 0], map)
  const tree = buildTreeMap(start, map, [start])
  const path = navigateTree(tree)
  console.log(path.map(_ => _.point));
  return path.length


  // Depth-first search (DFS)
  function navigateTree(node) {
    const dfp = (acc, _) => {
      if (_.value === target) {
        acc.push(_)
        return acc
      }
      const targetInMyChildren = _.children.reduce(dfp, [])
      if (targetInMyChildren.length > 0) {
        targetInMyChildren.unshift(_)
        return targetInMyChildren
      }
      return acc
    }

    return node.children.reduce(dfp, [])
  }

  function buildTreeMap(node, map2d, visited) {
    const [x, y] = node.point
    node.children = possibleMoves
      .map((([incx, incy]) => [x + incx, y + incy]))
      .filter(([nx, ny]) => {
    /**
     * REMOVE
     * + out of grid
     * + walls
     * + already visited points
     */
        if (nx < 0 || nx >= gridW
          || ny < 0 || ny >= gridH
          || map2d[ny][nx] === wall) {
          return false
        }

        return visited.findIndex(vis => vis.point[0] === nx && vis.point[1] === ny) === -1
      })
      .map(_ => {
        const newNode = buildNode(_, map2d)
        visited.push(newNode)
        return newNode
      })
    node.children.forEach(_ => buildTreeMap(_, map2d, visited))
    return node
  }

}

function buildNode(point, map) {
  const value = map[point[1]][point[0]]
  return {
    point,
    value,
    children: []
  }
}



const stepsCount = pathFinder([
  [1, 1, 1, 1],
  [0, 1, 1, 0],
  [0, 1, 1, 0],
  [0, 1, 0, 0],
  [0, 1, 1, 1],
  [0, 1, 1, 1],
  [9, 0, 1, 1],
  [1, 1, 1, 1],
  [1, 0, 1, 0],
  [1, 1, 1, 1]
])
console.log(stepsCount);

【讨论】:

    【解决方案2】:

    图表通常使用以下两种数据结构之一进行存储:

    1. 邻接列表 (http://en.wikipedia.org/wiki/Adjacency_list)

    2. 邻接矩阵 (http://en.wikipedia.org/wiki/Adjacency_matrix)

    各有各的空间和时间优势。

    您必须将要表示为图形的任何输入(例如,解析它)转换为上述数据结构之一。

    【讨论】:

    • 这就是我上面说的。我正在寻找解析部分。
    • 创建一个节点和边缘类。 Edge 可以有两个节点(每个端点一个)。节点可以有一组边(它连接到的每个节点一个)。一次解析一个字符的二维输入数组。创建 Node 对象的哈希集。当你遇到“-”时,检查它是否在 Hashset 中(例如,你已经为它创建了一个 Node),如果没有,创建一个新的 Node 对象。然后检查“-”周围的四个位置(上、下、左、右),如果看到任何“-”,则创建新的节点对象并将它们连接起来。
    猜你喜欢
    • 1970-01-01
    • 2017-08-27
    • 2021-01-17
    • 1970-01-01
    • 2011-06-22
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多