【问题标题】:Deleting Node from BST从 BST 中删除节点
【发布时间】:2016-07-13 06:29:32
【问题描述】:

我认为除了案例 2 (删除节点只有一个子树)之外,大多数案例都可以工作。我的测试用例是下面没有 1、2、3 和 4 节点的树:

这个程序告诉我 6 已从树中删除,但是当我尝试打印树时,它仍然显示 6 在树中。

public class RandomNode {

static int size;

public static class Node {

    int data;
    Node left;
    Node right;

    public Node(int data) {

        this.data = data;
        left = null;
        right = null;
        size++;
    }

}

// delete node in right subtree
public Node delete(Node root, int data) {
    // base case - if tree is empty
    if (root == null)
        return root;

    // search for deletion node 
    else if (data < root.data)
        root.left = delete(root.left, data);
    else if (data > root.data) {
        root.right = delete(root.right, data);

    } else {

        // case 1: deletion node has no subtrees
        if (root.left == null && root.right == null) {
            root = null;
            size--;
            System.out.println(data + " successfully deleted from tree (case1)");

            // case 2: deletion node has only one subtree
        } else if (root.left != null && root.right == null) {
            root = root.left;
            size--;
            System.out.println(data + " successfully deleted from tree (case2a)");
        } else if (root.left == null && root.right != null) {
            root = root.left;
            size--;
            System.out.println(data + " successfully deleted from tree (case2b)");

            // case 3: deletion node has two subtrees
            // *find min value in right subtree
            // *replace deletion node with min value
            // *remove the min value from right subtree or else there'll be
            // a duplicate
        } else if (root.left != null && root.right != null) {

            Node temp;
            if (root.right.right == null && root.right.left == null)
                temp = findMinNode(root.left);
            else
                temp = findMinNode(root.right);

            System.out.println(root.data + " replaced with " + temp.data);
            root.data = temp.data;

            if (root.right.right == null || root.left.left == null)
                root.left = delete(root.left, root.data);
            else
                root.right = delete(root.right, root.data);

            size--;
            System.out.println(temp.data + " succesfuly deleted from tree (case3)");

        }
    }

    return root;

}

// find min value in tree
public Node findMinNode(Node root) {

    while (root.left != null)
        root = root.left;
    System.out.println("min value: " + root.data);
    return root;

}

public void preOrderTraversal(Node root) {

    if (root == null)
        return;

    preOrderTraversal(root.left);
    System.out.println(root.data);
    preOrderTraversal(root.right);

}

public static void main(String[] args) {

    RandomNode r = new RandomNode();

    Node root = new Node(6);
    //root.left = new Node(2);
    root.right = new Node(9);
    //root.left.left = new Node(1);
    //root.left.right = new Node(5);
    //root.left.right.left = new Node(4);
    //root.left.right.left.left = new Node(3);
    root.right.left = new Node(8);
    root.right.right = new Node(13);
    root.right.left.left = new Node(7);
    root.right.right.left = new Node(11);
    root.right.right.right = new Node(18);

    r.delete(root, 6);
    r.preOrderTraversal(root);

}

}

【问题讨论】:

    标签: java binary-search-tree


    【解决方案1】:

    当你做 root = root.left;和大小 --,你还必须让 root.left = null。

    在这里,您只是将 root 设置为 root.left,但没有将 root.left 设置为 null。

    【讨论】:

    • 感谢您的回答。事实证明 Koos Gadella 的答案有效(通过设置 root = r.delete(root, 6) 而不仅仅是 r.delete(root, 6))。我也尝试了您的建议,但唯一的问题是它会删除所有子节点。
    【解决方案2】:

    这对我来说很难理解,因为我会按功能编写它。
    然而,

    if (root.right.right == null || root.left.left == null)
        root.left = delete(root.left, root.data);
    else
        root.right = delete(root.right, root.data);
    

    可能是错误的,因为它应该反映您之前的 findMinNode() 调用,因此应该是

    if(root.right.right == null && root.right.left == null)
        root.left = delete(root.left, root.data);
    

    调试的时候错误较多。

    首先,java 是按值传递的,所以如果你要删除顶部节点(根),你的指针也应该更新。因此,呼叫应该是root = r.delete(root, 6);

    其次,还有一个错误。案例 2a 将 root 分配给 root.left... 这是空的。应该是root.right。

    进行了这些更改后,输出变为:

    6 successfully deleted from tree (case2b)
    7
    8
    9
    11
    13
    18
    

    【讨论】:

    • 成功了!我只是认为我不需要设置 root = r.delete(root, someValue) 因为在我的删除方法中,我使用 root.left 或 root.right 设置了 root 的值。你知道为什么这不起作用吗?
    • Java 是按值传递的。因此,您的主循环有一个名为root 的变量。然后它调用Node.delete(root, 6)。通过调用它,它将root 的值(这是对包含对象数据的某些内存的引用)复制到Node.delete() 方法中的root 参数的值。所以 main.root 和 node.root 都是引用,都引用值为 6 的节点。删除完成它的工作,删除的根变量被修改为引用不同的节点(节点(7))。但是主节点的根仍然指向节点(6)。删除后,main方法打印它的root
    • 这对我来说终于有意义了。谢谢库斯!!
    猜你喜欢
    • 2021-10-23
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 2016-11-11
    • 1970-01-01
    相关资源
    最近更新 更多