简体   繁体   English

为什么我的二叉搜索树删除递归没有结束?

[英]Why Is My Binary Search Tree Delete Recursion Not Ending?

I am trying to implement a binary search tree using Java.我正在尝试使用 Java 实现二叉搜索树。 One of the functions that I want to create is the delete function.我要创建的功能之一是删除 function。 This will consists of two methods, one called delete and the other called getNodeToDelete .这将包含两种方法,一种称为delete ,另一种称为getNodeToDelete The getNodeToDelete method is a helper function for the delete method. getNodeToDelete方法是删除方法的助手 function。

The getNodeToDelete method is recursive, and basically returns the node that the user wants to delete from the tree. getNodeToDelete方法是递归的,基本上返回用户想要从树中删除的节点。 Using the node that is returned from this getNodeToDelete method, the non-recursive delete method basically makes important decisions on how to delete this node depending on different cases (eg is it a leaf node, is it a root node etc.).使用从这个getNodeToDelete方法返回的节点,非递归删除方法基本上根据不同的情况(例如,它是叶节点,它是根节点等)来决定如何删除这个节点。

This is the non-recursive delete method:这是非递归删除方法:

 /**
     * Deletes the relevant node (according to the key inputted by the user), using two helper functions:
     * getNodeToDelete(int deleteKey, Node root) and getMinRight(Node nodeToDelete).
     * @param key
     */
    public void delete(int key) {
        if (root.left == null && root.right == null) {
            if (root.key == key) {
                root = null;
                System.out.println("It reached the first if-statement of the delete() method.");
            }
        }
        Node nodeToDelete = getNodeToDelete(key, root); //The node that is returned from its helper function.
        System.out.println("This is the node to delete: " + nodeToDelete.key);
        if (nodeToDelete.right == null && nodeToDelete.left == null) {  //If the nodeToDelete is a leaf.
            nodeToDelete = null;
//            System.out.println("This is the key of the deleted node: " + nodeToDelete.key);
            return;
        } else if (nodeToDelete.right == null) {  //If the nodeToDelete has an empty right tree.
            Node immediateLeftNode = nodeToDelete.left;
            nodeToDelete.key = immediateLeftNode.key;
            nodeToDelete.left = immediateLeftNode.left;
            nodeToDelete.right = immediateLeftNode.right;
        } else if (nodeToDelete.right != null) {  //If the nodeToDelete has a non-empty right tree
            if (nodeToDelete.right.left == null) {  //If the left branch of the right branch of nodeToDelete is empty.
                nodeToDelete.key = nodeToDelete.right.key;
                nodeToDelete.right = nodeToDelete.right.right;
            } else {
                Node replacementNode = getMinRight(nodeToDelete);
                nodeToDelete.key = replacementNode.key;
            }
        }
    }

And this is the recursive getNodeToDelete method:这是递归的getNodeToDelete方法:

/**
     * Assumption: the key does exist in the tree.
     * Returns the node that the user wants to delete, based on the key that the user inputs.
     * @param deleteKey
     * @param startingRoot
     * @return
     */
    public Node getNodeToDelete(int deleteKey, Node startingRoot) {
        if (startingRoot == null) {
            return null;
        }

        if (startingRoot.key == deleteKey) {
            return startingRoot;
        }

        if (deleteKey < startingRoot.key) {
            getNodeToDelete(deleteKey, startingRoot.left);
        }

        getNodeToDelete(deleteKey, startingRoot.right);
        return startingRoot;
    }

The problem is, the helper function, getNodeToDelete , traverses down the tree to one of its nodes, for example, the leaf node of value -12.问题是,帮助程序 function, getNodeToDelete向下遍历树到其节点之一,例如值为 -12 的叶节点。 Then it returns that node, but the recursive method getNodeToDelete seems to not end.然后它返回该节点,但递归方法getNodeToDelete似乎没有结束。 It then traverses back up to the root node again, always resulting in the returned value being the root node.然后它再次遍历回到根节点,始终导致返回的值是根节点。

I know that there are many different approaches to implementing a binary search tree in Java, but this recursion problem is bothering me and I really want to know the reason behind the failure of this.我知道在 Java 中实现二叉搜索树有很多不同的方法,但是这个递归问题困扰着我,我真的很想知道失败背后的原因。

Please let me know if you need more clarification.如果您需要更多说明,请告诉我。 Thanks谢谢

Someone answered my question before they deleted it, but their answer definitely helped me in finding a solution.有人在删除之前回答了我的问题,但他们的回答绝对帮助我找到了解决方案。 So, thank you whoever it was.所以,谢谢你。

Basically, my recursion (in the recursive method, getNodeToDelete ), was always returning my root node because I was not returning the results of the recursion.基本上,我的递归(在递归方法中, getNodeToDelete )总是返回我的根节点,因为我没有返回递归的结果。 Thus, discarding my wanted data instead of letting it recur back to me.因此,丢弃我想要的数据而不是让它再次出现在我身上。 This is quite difficult to explain but basically, this is the getNodeToDelete method after fixing:这很难解释,但基本上,这是修复后的getNodeToDelete方法:

/**
     * Assumption: the key does exist in the tree.
     * Returns the node that the user wants to delete, based on the key that the user inputs.
     * @param deleteKey
     * @param startingRoot
     * @return
     */
    public List<List> getNodeToDelete(int deleteKey, Node startingRoot, Node parentNode, String directionFlag) {
        List<Node> nodes = new ArrayList<>();
        nodes.add(startingRoot);
        nodes.add(parentNode);

        List<List> nodeData = new ArrayList<>();
        nodeData.add(nodes);
        List<String> direction = new ArrayList<>();
        direction.add(directionFlag);

        nodeData.add(direction);

        if (startingRoot == null) {
            return null;
        }

        if (startingRoot.key == deleteKey) {
            System.out.println("This is node that is FINALLY RETURNED " + startingRoot.key);
            return nodeData;
        }

        if (deleteKey < startingRoot.key) {
            System.out.println("This is node that is returned " + startingRoot.key);
            return getNodeToDelete(deleteKey, startingRoot.left, startingRoot, "left"); //Added return statement here.
        }

        System.out.println("This is node that is returned " + startingRoot.key);
        return getNodeToDelete(deleteKey, startingRoot.right, startingRoot, "right");  //Added return statement here.
    }

Other than couple other things that I changed, which were because of some errors in my delete function, the thing that allowed my getNodeToDelete method to return the node that the user wanted to delete, was by adding return statements in the places that are commented with Added return statement here in the above code snippet.除了我更改的其他几件事之外,这是因为我的删除function 中的一些错误,允许我的getNodeToDelete方法返回用户想要删除的节点的事情是通过在注释的地方添加返回语句在上面的代码片段中添加了 return 语句

This is still quite mind-blowing to me as to why I overlooked this important step behind recursion, so I need to think on it more.对于为什么我忽略了递归背后的这一重要步骤,这仍然让我感到非常震惊,所以我需要更多地思考它。 But, basically, the moral of the story is, make sure to actually return your results from the recursion, instead of simply calling on the function recursively!但是,基本上,这个故事的寓意是,确保真正从递归中返回结果,而不是简单地递归调用 function!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM