递归二叉搜索树删除方法

时间:2013-11-02 23:52:18

标签: java recursion binary-search-tree

首先,这是家庭作业,所以把它放在那里。

我应该用特定的方法实现二叉搜索树:

void insert(String),boolean remove(String)和boolean find(String)。

我已经能够成功编程并测试插入和查找方法,但是在删除时遇到了困难。

我的程序中发生的事情是删除实际上并没有从树中删除任何内容,我相信这是因为它只引用当前节点的本地创建,但我可能是错的。我想我可以实现我需要测试的不同情况的逻辑(可能需要帮助删除一个有两个子节点的节点,但我想我从概念上得到它)主要是试图理解我需要做什么不同来引用

中正确的树
current = null; // case

这是我到目前为止所得到的:

public boolean remove(String title)
{
    return remove(root, title);
}
private boolean remove(BSTNode current, String title)
{
    if (current == null)
    {
        return false;
    }
    if (current.data == title)
    {
    if (current.left_child !=null && current.right_child != null)
    {
        return true;  // returning true since I haven't finished writing this case
    }
    else if (current.left_child == null && current.right_child == null)
        {
        current = null;  // this should remove the node from tree but it doesn't
        return true; 
    }

    else if (current.left_child != null && current.right_child == null)
    {
        current = current.left_child;    // don't think this is right
        return true;
    }
    else if (current.right_child != null && current.left_child == null)
    {
        current = current.right_child;   // not sure about this
        return true;
    }

    }
root = current;
if (title.compareToIgnoreCase(current.data) == -1)
{
    return remove(current.left_child, title);
}
    else 
{
    return remove(current.right_child, title);
}
}

非常感谢任何知识。

1 个答案:

答案 0 :(得分:2)

一个节点由它的父节点引用(根节点除外,该节点由BST本身引用)。要从树中删除节点,您需要在父节点中将该引用设置为null

你现在要做的是:

Before:
parent.left ---> node <--- current

After setting current = null:
parent.left ---> node      current ---> null

即当前引用null,但不会更改父项(仅限该局部变量)。

在你的删除方法中,你也需要传递父项(或者在父母的调用中处理两个子项,无论你更喜欢什么)。

顺便说一下:永远不会将字符串与==进行比较,例如参见this question


如何在不使用显式存储每个节点中的父节点的情况下找到节点及其父

我会说在循环中执行此操作更简单,而不是使用递归,但两者都可以。循环中:

BSTNode parent = null;
BSTNode current = root;
boolean found = false;
while (!found && current != null) {
    int compare = title.compareToIgnoreCase(current.data);
    if (compare == 0) {
        found = true;
    } else {
        parent = current;
        if (compare < 0) {
            current = current.left;
        } else {
            current = current.right;
        }
    }
}
if (!found) {
    // title was not found
} else if (parent == null) {
    // found the root
} else {
    // found another node
}

通过递归很烦人,因为你想要一个返回节点和它的父节点的方法。你需要一些简单的内部类来解决这个问题:

private class NodeAndParent {
    public BSTNode node;
    public BSTNode parent;
    public NodeAndParent(BSTNode node, BSTNode parent) {
        this.node = node;
        this.parent = parent;
    }
}

private boolean find(String title, NodeAndParent current) {
    if (current.node == null) {
        return false; // not found
    } else {
        int compare = title.compareToIgnoreCase(current.node.data);
        if (compare == 0) {
            return true; // found
        } else {
            current.parent = current.node;
            if (compare < 0) {
                current.node = current.node.left;
            } else {
                current.node = current.node.right;
            }
        }
    }
}

private boolean remove(String title) {
    NodeAndParent nodeAndParent = new NodeAndParent(root, null);
    boolean found = find(title, nodeAndParent);
    if (!found) {
        // title was not found
    } else if (nodeAndParent.parent == null) {
        // found the root
    } else {
        // found another node
    }
}