如何从Java中的二进制搜索树中“删除”节点?

时间:2014-03-08 23:08:17

标签: java binary-search-tree

我用Java创建了一个二叉搜索树,但是我在删除节点部分时遇到了麻烦。当它只有1个儿子的时候我设法擦除了节点,并且我有想法在它有2个儿子时进行删除,无论如何我没有儿子时使用的方法(当它是一片叶子时)不起作用Java的。通常在C ++中我会将Node指定为“null”,但它在这里不起作用。

if (numberOfSons(node) == 0) {
            node= null;
            return true;
}

这是处理归零部分的代码部分。当我调试它时,它正在引用正确的节点并且它为它分配空值,但是当我返回到我正在为我的树调用delete方法的Frame时,节点仍然在那里。在Java中“空”对象的正确方法是什么?我认为这里的一切都是指针,所以这会起作用,但我认为它没有。

2 个答案:

答案 0 :(得分:6)

当你null某事时,你只需在null所在的范围内进行参考。它不会影响外面的任何事情。

让我举例解释。假设你有一个方法foo:

public void foo(Node node) {
    node = null;
    if(node == null) {
      System.out.println("node is null");
    } else {
      System.out.println("node is not null");
    }
}

现在你这样称呼它:

public void doSomething() {
   Node node = new Node();
   foo(node);
    if(node == null) {
      System.out.println("Original node is null");
    } else {
      System.out.println("Original node is not null");
    }   
}

在您的控制台中,您将获得:

node is null
original node in not null

原因是它不是指针,它是一个参考。当您null引用时,您只需说“将此引用同义词设为null”。这并不意味着该对象被删除,它可能仍然存在于其他地方。 无法删除java中的对象。您所能做的就是确保没有其他对象指向它们,垃圾收集器将删除对象(有时)。

答案 1 :(得分:1)

除了重新插入左或右子树之外什么都没有。例如:

class BinaryTree<T extends Comparable<T>> {
    class Node {
        Node left;
        Node right;
        T value;
    }

    Node root;

    void delete(T soughtValue) {
        root = deleteRec(root, soughtValue);
    }

    Node deleteRec(Node node, T soughtValue) {
        if (node == null) {
            return null;
        }
        int comparison = soughtValue.compareTo(node.value);
        if (comparison < 0) {
            node.left = deleteRec(node.left, soughtValue);
        } else if (comparison > 0) {
            node.right = deleteRec(node.right, soughtValue);
        } else {
            if (node.left == null) {
                return node.right;
            } else if (node.right == null) {
                return node.left;
            } else {
                // Two subtrees remain, do for instance:
                // Return left, with its greatest element getting
                // the right subtree.
                Node leftsRightmost = node.left;
                while (leftsRightmost.right != null) {
                    leftsRightmost = leftsRightmost.right;
                }
                leftsRightmost.right = node.right;
                return node.left;
            }
        }
        return node;
    }
}

由于Java没有像C ++ Node*&中那样的别名参数 - 一种输入输出参数,我在这里使用deleteRec的结果。在java中,作为对象变量的任何函数参数都不会使用另一个对象实例更改变量。 这是单继承之类的语言设计决策之一。