2013-12-22 153 views
0

我正在构建一个二进制搜索树在JavaScript中的一些算法/数据结构的做法。在执行delete()时遇到了一个有趣的场景,我很好奇是否有更好的方法来解决这个问题。这真的没有任何与二叉树,但这里的准系统,你需要知道的明白我的问题:Javascript参考

function innerDelete(node, parent) { 
      switch (node.countChildren(node)) { 
       case 0: 
        ... 
       case 1: 
        if (node.left) 
         node = node.left; 
        else 
         node = node.right; 
        ... 

道具的人谁可以立即看到这个问题。该树由节点对象组成,每个节点对象的属性为{ value, left, right }。这种删除方法是直接更新对象,所以我不必管理更新对子节点的父引用。问题是在node = node.leftnode = node.right期间重新分配节点只是将本地引用重新分配给此变量,而不是实际的node对象。有没有办法直接更新对象本身?替代方案,我想出了是有点难看,所以我希望有一个更好的办法:

var branch = (parent.left == n ? 'left' : 'right'); 
if (node.left) 
    p[branch] = node.left; 
else 
    p[branch] = node.right; 
+1

就在你的解决方法了''parent' p'?如果是这样,解决方法很好。 JavaScript中没有指针,所以这是正确的方法。 – bfavaretto

+0

是的,只是我的错误副本。这是可以接受的做事方式。 – Clev3r

回答

0

的问题是,节点在重新分配节点= node.left或节点= node.right只重新分配本地引用这个变量, 而不是实际的节点对象

这是因为该值node是一个参考,所以它不是说你改变的node本地副本,您要更改参考。因此,你实际上并没有改变对象本身。

更新树的更清晰的方法是使用递归,每次递归调用都会在返回时更新左右节点。

例如:

root = delete(root, target); 

function delete(node, target) { 
    // Not found 
    if (node === null) return null; 
    // Found 
    if (node.value === target) { 
     // If there's children 
      // If has both left and right child 
      var newNode = minimum(node.right); 
      deleteMin(node.right); 
      newNode.left = node.left; 
      newNode.right = node.right; 
      return newNode; 
     // Else 
      return null; 
    } 
    // Update 
    node.left = delete(node.left, target); 
    node.right = delete(node.right, target); 
    return node; 
} 
+0

我发现递归删除不像迭代那么干净。例如,上面的'minimum()'和'deleteMin()'是用迭代版本隐含地实现的。 – Clev3r