Arrays 如何从二维数组构建图形?

Arrays 如何从二维数组构建图形?,arrays,algorithm,graph,Arrays,Algorithm,Graph,我正在努力学习图形结构和算法。从概念上讲,我理解DFS、BFS,并且我可以通过一个图来实现它们,但是传统上图是如何组成的呢 通常,我将它们视为以边为指针的节点列表、边与其连接的节点的列表,或者是一个二维矩阵,其中两个arr[node_a][node_b]的交点是边的权重 当涉及到用输入构建它时,我不知道从哪里开始 例如,当提供一个二维网格(在线pacman问题)时,您将如何构建一个图,其中p是源节点,而-,是树中的节点 %%%%%%%%%%%%%%%%%%%% %--------------%-

我正在努力学习图形结构和算法。从概念上讲,我理解DFS、BFS,并且我可以通过一个图来实现它们,但是传统上图是如何组成的呢

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

当涉及到用输入构建它时,我不知道从哪里开始

例如,当提供一个二维网格(在线pacman问题)时,您将如何构建一个图,其中p是源节点,而-,是树中的节点

%%%%%%%%%%%%%%%%%%%%
%--------------%---%
%-%%-%%-%%-%%-%%-%-%
%--------P-------%-%
%%%%%%%%%%%%%%%%%%-%
%.-----------------%
%%%%%%%%%%%%%%%%%%%%
或者,如果提供了邻接列表,您将如何构建它


我知道这可能是一个大问题,因为问题相当复杂。欢迎链接到文档!从入门级开始,我一直很难找到任何图形。

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

  • 邻接列表()

  • 邻接矩阵()

  • 每个都有自己的空间和时间优势


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

    为此,我编写了此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);
    
    const wall=0
    常数平坦=1
    常数目标=9
    //没有对角线
    常量可能移动=[
    [-1,0],//nord
    [0, +1],
    [+1,0],//sud
    [0, -1],
    ]
    功能探路者(地图){
    常量gridW=map[0]。长度
    const gridH=map.length
    const start=buildNode([0,0],map)
    const tree=buildTreeMap(开始,映射,[start])
    const path=navigateTree(树)
    log(path.map(=>wu.point));
    返回路径长度
    //深度优先搜索(DFS)
    函数navigateTree(节点){
    常数dfp=(acc,)=>{
    如果(u.value==目标){
    加速推力
    返回acc
    }
    const targetInMyChildren=\ u0.children.reduce(dfp,[])
    如果(targetInMyChildren.length>0){
    targetMyChildren.unshift(41;
    返回targetMyChildren
    }
    返回acc
    }
    返回node.children.reduce(dfp,[])
    }
    函数buildTreeMap(节点,map2d,已访问){
    常数[x,y]=节点点
    node.children=possibleMoves
    .map((([incx,incy])=>[x+incx,y+incy]))
    .filter(([nx,ny])=>{
    /**
    *除去
    *+电网外
    *+墙
    *+已访问点
    */
    如果(nx<0 | | nx>=gridW
    ||ny<0 | | ny>=gridH
    ||map2d[ny][nx]==墙){
    返回错误
    }
    返回已访问的.findIndex(vis=>vis.point[0]==nx&&vis.point[1]==ny)=-1
    })
    .map(=>{
    const newNode=buildNode(\ux,map2d)
    已访问。推送(新节点)
    返回新节点
    })
    node.children.forEach(=>buildTreeMap(z,map2d,已访问))
    返回节点
    }
    }
    功能构建节点(点、地图){
    常量值=映射[点[1]][点[0]]
    返回{
    指向
    价值
    儿童:[]
    }
    }
    const stepsunt=探路者([
    [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]
    ])
    控制台日志(StepScont);
    
    事实上,如果你得到了这个网格,为什么要制作一个图形?你可以将网格用作隐式图形,对吗?@harold我怎么能这样做?这就是我上面说的。我正在寻找解析部分。创建一个节点和边类。边可以有两个节点(每个端点一个)。节点可以有一组边(连接到的每个节点一个边)。一次解析一个字符的2D输入数组。创建一组节点对象。当您遇到一个“-”时,请检查它是否在哈希集中(例如,您已经为它创建了一个节点),如果没有,请创建一个新的节点对象。然后检查“-”(顶部、底部、左侧、右侧)周围的四个位置,如果看到任何“-”,请创建新的节点对象并将它们连接起来。