二进制搜索树删除

时间:2012-04-28 21:58:45

标签: c++ tree binary-search-tree

我目前正在使用C ++编写二进制搜索树,我已经到了必须编写删除/删除功能的阶段(使用递归方法,x = change(x))。我有两个选择:

  • 停止在要删除的节点的父节点上;

  • 到达要删除的节点,然后调用将要执行的功能 返回父母

  

方法1:更便宜,更多代码

     

方法2:代码更少,更昂贵

根据你的哪种方法更好,为什么?

3 个答案:

答案 0 :(得分:1)

我不同意这些是你唯一的两个选择。

我认为更简单的解决方案是询问每个节点应该删除的天气。如果它确定是,那么它将被删除并返回应该替换它的新节点。如果它决定否则它会自行返回。

// pseudo code.
deleteNode(Node* node, int value)
{
    if (node == NULL) return node;

    if (node->value == value)
    {
        // This is the node I want to delete.
        // So delete it and return the value of the node I want to replace it with.
        // Which may involve some shifting of things around.
        return doDelete(node);
    }
    else if (value < node->value)
    {
        // Not node. But try deleting the node on the left.
        // whatever happens a value will be returned that
        // is assigned to left and the tree will be correct.
        node->left = deleteNode(node->left, value);
    }
    else
    {
        // Not node. But try deleting the node on the right.
        // whatever happens a value will be returned that
        // is assigned to right and the tree will be correct.
        node->right = deleteNode(node->right, value);
    }
    // since this node is not being deleted return it.
    // so it can be assigned back into the correct place.
    return node;
}

答案 1 :(得分:0)

最好的方法是遍历要删除的节点的父节点,然后删除该子节点。最终使用此方法始终访问子节点,因为您始终必须确认子节点是您要删除的节点。

答案 2 :(得分:0)

我发现一般来说,为树数据结构编写函数的最有效形式是以下伪格式格式。

    function someActionOnTree() {
         return someActionOnTree(root)
    }

    function someActionOnTree (Node current) {
         if (current is null) {
              return null
         }
         if (current is not the node I seek) {
              //logic for picking the next node to move to
              next node = ...

              next node = someActionOnTree(next node)
         }
         else {
              // do whatever you need to do with current
              // i.e. give it a child, delete its memory, etc
              current = ...
         }
         return current;
    }

此递归函数递归数据结构的顶点集。对于算法的每次迭代,它要么寻找一个节点来递归函数,要么用该节点上算法迭代的值覆盖数据结构对该节点的引用。否则,它会覆盖节点的值(并可能执行不同的逻辑集)。最后,该函数返回对参数节点的引用,这对于覆盖步骤是必不可少的。

这是我在C ++中为树数据结构找到的最有效的代码形式。这些概念也适用于其他结构 - 您可以使用此形式的递归,其中返回值始终是对数据结构的平面表示中的固定点的引用(基本上,总是返回应该在您现场的任何内容) “看着。”

这是一种将这种风格应用于二元搜索树删除功能以修饰我的观点。

function deleteNodeFromTreeWithValue( value ) {
     return deleteNodeFromTree(root, value)
}

function deleteNodeFromTree(Node current, value) {
     if (current is null) return null
     if (current does not represent value) {
          if (current is greater than my value) {
               leftNode = deleteNodeFromTree(leftNode, value)
          } else {
                rightNode = deleteNodeFromTree(rightNode, value)
          }
      }
      else {
           free current's memory
           current = null
      }
      return current
}

显然,还有很多其他方法可以编写这段代码,但从我的经验来看,这已经证明是最有效的方法。请注意,覆盖指针并不会影响性能,因为硬件已经缓存了节点。如果你正在研究提高搜索树的性能,我建议你研究一下专门的树,比如自平衡树(AVL树),B树,红黑树等。