广度优先搜索二进制搜索树javascript实现

时间:2017-05-01 16:40:52

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

我有以下代码在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循环。我该如何实现这个功能?我知道该函数会产生意外行为吗?我应该做些什么改正?

2 个答案:

答案 0 :(得分:2)

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

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

// 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

时处理更大的数据结构

答案 1 :(得分:1)

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

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

如果记忆存在问题,还有另一种方法可以做到。您可以只记住深度,然后每次重做迭代,而不是记住给定级别的节点数组。所以你有一个函数,它采用一个自然数n并迭代树,但不会超过n,并做任何你想要做的事情{{1只有水平;然后为n的所有值调用此函数,直到没有剩余节点为止。

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