深度优先遍历和广度优先遍历(JS)

427 阅读1分钟

深度优先遍历:以纵向的维度遍历数据,从某个顶点开始,先访问它的子节点,如果没有子节点则访问它的兄弟节点,以这个子节点为顶点,重复此步骤,直到所有的节点被访问完为止。

广度优先遍历:以横向的维度遍历数据,从某个顶点开始,先访问它的兄弟节点,访问完后再访问第一个节点的子节点,再以个子节点为顶点,重复此步骤,直到所有的节点被访问完为止。

深度优先遍历递归实现:

function dfs(node, nodes) {
  nodes = nodes || [];
  if (node) {
    nodes.push(node);
    let child = node.children;
    for (let i = 0; i < child.length; i++) {
      dfs(child[i], nodes);
    }
  }
  return nodes;
}

深度优先遍历非递归实现:

function dfs(node) {
  let nodes = [];
  if (node) {
    // 利用栈后进先出的特性,取最后一个出来加进nodes里面
    let stacks = [];
    stacks.push(node);
    while (stacks.length) {
      let item = stacks.pop(); // 取出最后一个
      nodes.push(item); // 加进nodes里面
      let child = item.children;
      for (let i = child.length - 1; i >= 0; i--) {
        // 把后面的子节点先加进栈里面,再在最后面取出来
        stacks.push(child[i]);
      }
    }
  }
  return nodes;
}

广度优先遍历非递归实现:

function bfs(node) {
  let nodes = [];
  if (node) {
    // 利用队列先进先出的特性,取第一个出来加进nodes里面
    let queue = [];
    queue.push(node);
    while (queue.length) {
      let item = queue.shift();
      nodes.push(item);
      let child = item.children;
      for (let i = 0; i < child.length; i++) {
        // 按顺序从左到右加进队列
        queue.push(child[i]);
      }
    }
  }
  return nodes;
}

广度优先遍历优化:

function bfs(node) {
  let nodes = [];
  if (node) {
    let queue = [];
    queue.push(node);
    let index = 0;
    while (index < queue.length) {
      let item = queue[index++];
      nodes.push(item);
      let child = item.children;
      for (let i = 0; i < child.length; i++) {
        queue.push(child[i]);
      }
    }
  }
  return nodes;
}