二叉搜索树删除 我在C++中使用二进制搜索树,现在已经到了我必须写删除/删除函数的阶段(使用递归方法, x= change(x))。我有两个选择:

二叉搜索树删除 我在C++中使用二进制搜索树,现在已经到了我必须写删除/删除函数的阶段(使用递归方法, x= change(x))。我有两个选择:,c++,tree,binary-search-tree,C++,Tree,Binary Search Tree,在要删除的节点的父节点处停止 访问要删除的节点,然后调用将 返回父对象 方法1:成本更低,代码更多 方法2:代码更少,成本更高 你认为哪种方法更好,为什么 最好的方法是遍历到要删除的节点的父节点,然后删除该子节点。最终使用这种方法,您总是访问子节点,因为您总是必须确认子节点是您要删除的节点。最好的方法是遍历到要删除的节点的父节点,然后删除该子节点。最终,使用这种方法,您总是会访问子节点,因为您必须始终确认子节点是您要删除的节点。我发现,通常为树数据结构编写函数的最有效形式是以下psuedoco

在要删除的节点的父节点处停止

  • 访问要删除的节点,然后调用将
    返回父对象

  • 方法1:成本更低,代码更多

    方法2:代码更少,成本更高


    你认为哪种方法更好,为什么

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

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

    我发现,通常为树数据结构编写函数的最有效形式是以下psuedocode格式

        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树、红黑树等。

    我发现通常为树数据结构编写函数的最有效形式是以下伪代码格式

        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树、红黑树等。

    我不同意这是您仅有的两种选择

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

    // 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;
    }
    
    //伪代码。
    deleteNode(节点*节点,int值)
    {
    如果(node==NULL)返回节点;
    如果(节点->值==值)
    {
    //这是我要删除的节点。
    //因此,删除它并返回我要替换它的节点的值。
    //这可能涉及到一些事情的转变。
    返回doDelete(节点);
    }
    else if(值<节点->值)
    {
    //不是节点。请尝试删除左侧的节点。
    //无论发生什么,都会返回一个
    //被分配到左侧,树将是正确的。
    节点->左=删除节点(节点->左,值);
    }
    其他的
    {
    //不是节点。请尝试删除右侧的节点。
    //无论发生什么,都会返回一个
    //被分配到右侧,树将是正确的。
    节点->右侧=删除节点(节点->右侧,值);
    }
    //由于未删除此节点,请返回它。
    //因此,可以将其分配回正确的位置。
    返回节点;
    }
    
    我不同意这是你仅有的两个选择

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

    // 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;
    }
    
    //伪代码。
    deleteNode(节点*节点,int值)
    {
    如果(node==NULL)返回节点;
    如果(节点->值==值)
    {
    //这是我要删除的节点。
    //因此,删除它并返回值