【问题标题】:Breadth first search binary search tree javascript implementation广度优先搜索二叉搜索树javascript实现
【发布时间】:2017-05-01 16:40:51
【问题描述】:

我有以下在 JavaScript 中实现 BST 树的代码。

function Node(value) {
  this.left = null;
  this.right = null;
  this.value = value;
}

function BinarySearchTree() {
  this.root = null;
  return;
}

BinarySearchTree.prototype.push = function(value) {

  if (!this.root) {
    this.root = new Node(value);
    return;
  }

  var currentRoot = this.root;
  var newNode = new Node(value);
  while (currentRoot) {
    if (value < currentRoot.value) {
      if (!currentRoot.left) {
        currentRoot.left = newNode;
        break;
      } else {
        currentRoot = currentRoot.left;
      }
    } else {

      if (!currentRoot.right) {
        currentRoot.right = newNode;
        break;
      } else {
        currentRoot = currentRoot.right;
      }

    }

  }

}

var a = new BinarySearchTree();
a.push(27);
a.push(14);
a.push(35);
a.push(10);
a.push(19);
a.push(31);
a.push(42);

我正在尝试实现一个可以对树进行广度优先遍历的函数。这是我到目前为止所尝试的。

console.log(a.root.value);
traverse(a.root);

//function to traverse 
function traverse(node) {

  currentNode = node;
  while (currentNode.left) {
    displayNodes(currentNode);
    parent = currentNode;
    currentNode = currentNode.left;
    displayNodes(currentNode);
    if(parent.right!=null){
    displayNodes(parent.right);
    }
  }
}

//function that displays the left and right node of a node 
function displayNodes(node) {


  if (node.left != null) {
    console.log(node.left.value);
  }
  if (node.right != null) {
    console.log(node.right.value);
  }
}

我无法实现一个可以处理大量数据的函数。我不确定遍历的递归方法是否更好或使用 while 循环。如何实现该功能?我知道该功能会产生意想不到的行为吗?我应该做哪些更正?

【问题讨论】:

  • 它是什么让您认为它无法扩展到大量数据?

标签: javascript data-structures binary-search-tree traversal recursive-datastructures


【解决方案1】:

您当前遍历从根节点到最左边叶子的路径。

一个简单的非递归广度优先遍历函数在每个遍历的节点上调用回调,如下所示:

// Breadth-first traversal:
function traverse(node, cb) {
  var current = [node];
  while (current.length > 0) {
    var next = [];
    for (var node of current) {
      cb(node);
      if (node.left) next.push(node.left);
      if (node.right) next.push(node.right);
    }
    current = next;
  }
}

// Example:
traverse(root, function(node) {
  console.log(node.value);
});

它的工作原理是保留一组已经发现或遍历的节点current,最初只包含您的根节点。现在,您迭代地将该列表中的每个节点替换为其子节点。在上面的函数中,孩子存储在一个next 数组中。在每次迭代结束时,current 中当前级别的所有节点都将替换为 next 中下一个更深级别的所有子节点。另见@DavidKnipe's answer给出的第一个建议。

非递归方法的优点是不受调用堆栈大小限制。这在理论上允许您在call stack size is limited 时处理更大的数据结构。

【讨论】:

  • 感谢您的详细回答,您能解释一下代码是如何工作的吗?
  • @Arihant 我稍微解释了这个函数。如果您有任何问题,请告诉我。
【解决方案2】:

如果您正在寻找一种使用 O(1) 内存进行 BFS 的方法,我认为没有什么好的方法可以做到这一点。 (但 DFS 是另一回事。你确定它必须是 BFS 吗?)

我认为有两种方法可以做到这一点。您可以从数组[this.root] 开始,然后编写一个函数来遍历节点数组,然后返回这些节点的子节点数组。然后在子数组上调用该函数,并继续向下遍历树,直到得到一个空数组。

如果内存是个问题,还有另一种方法可以解决。您可以只记住深度,然后每次重做迭代,而不是记住给定级别的节点数组。所以你有一个函数,它接受一个自然数n 并在树上迭代,但不会比n 更深,并且只在nth 级别上做你想做的任何事情;然后为n 的所有值调用此函数,直到没有剩余节点为止。

最后一个可能听起来很浪费,但如果树的最后几级包含大部分节点,它可能不会太糟糕。这取决于您的数据集和计算能力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多