从二叉搜索树中递归删除

这是家庭作业;请不要只是给我代码

我有两种方法:和.remove(T data)removeRec(Node<T> node, T data)

在当前状态下,我的代码似乎只删除了BST的节点。root

@Override
public T remove(T data) {
    if (data == null) {
        throw new IllegalArgumentException("Data is null");
    }
    if (root == null) {
        throw new java.util.NoSuchElementException("BST is empty");
    } else {
        size--;
        BSTNode<T> dummy = new BSTNode<T>(null);
        return removeRec(root, data, dummy).getData(); //This is probably wrong too
    }
}

/**
 * Helper method to recursively search for, and remove the BSTNode with
 * the given data in it
 * @param  node is the node we're currently at
 * @param  data is the data we're looking for
 * @param  temp I have no idea why
 * @return node that was removed
 */
private BSTNode<T> removeRec(BSTNode<T> node, T data, BSTNode<T> temp) {
    if (compare(data, node.getData()) < 0) {
        temp.setLeft(removeRec(node.getLeft(), data, temp));
    } else if (compare(data, node.getData()) > 0) {
        temp.setRight(removeRec(node.getRight(), data, temp));
    } else if (node.getLeft() != null && node.getRight() != null) {
        temp.setData(findMin(node.getRight()).getData());
        temp.setRight(removeRec(node.getRight(), data, temp));
    } else {
        if (node.getLeft() != null) {
            temp = node.getLeft();
        } else {
            temp = node.getRight();
        }
    }
    return temp;
}

private int compare(T a, T b) {
    return a.compareTo(b);
}

我的老师告诉我(作为提示),我应该看看第三个参数传入方法的内容,在这种情况下,.我不明白这有什么帮助,或者如何利用它。我不明白使用第三个参数有什么帮助;我在网上找不到任何关于你为什么要这样做的东西。BSTNode<T> temp


答案 1

当您尝试从二叉搜索树中删除时,有三种主要可能性:data

  1. data小于当前节点值:在左侧子树上调用 remove 或如果子树为 null 则抛出 a。NoSuchElementException
  2. data大于当前节点值:在右侧子树上调用 remove 或如果子树为 null 则抛出 a。NoSuchElementException
  3. data等于当前节点值。

1 和 2 非常简单,但 3 还有四种情况需要考虑:

3.1. 当前节点是一个叶子:左子树和右子树都为空。只需将父节点中对当前节点的引用替换为 null 即可。

3.2. 当前节点只有左子节点:需要使当前节点的父节点指向左子树,从而删除当前点。为此,您可以实现一个函数,该函数将检查当前点是在级的左子树还是右子树上,并相应地替换它。调用它看起来像这样:

replaceNodeInParent(node, node.getLeft(), parent);

3.3. 当前节点只有正确的子节点:与 3.4 类似,但使用 代替 .getRight()getLeft()

3.4. 当前节点同时具有左子节点和右子节点:应保持 BST 的属性,即左侧的所有节点都小于当前节点,右侧的所有节点都大于当前节点。为此,您应该在右侧找到最小值,将其复制到当前节点,然后将其从右侧子树中删除。像这样:

BSTNode<T> successor = findMin(node.getRight());
node.setData(successor.getData());
removeRec(node.getRight(), successor.getData(), node);

看起来您没有对节点的引用。如果是这样,我相信这就是第三个论点应该是什么。每次替换当前节点时都需要对父节点的引用,因此可以根据需要设置父级左子树或右子树。BSTNoderemoveRec

如需进一步阅读,您可以查看维基百科上关于二叉搜索树的这篇文章


答案 2