简体   繁体   English

删除二叉搜索树中的节点

[英]Deleting an node in Binary search tree

This is not an homework. 这不是家庭作业。 I am just totally blocked on this. 我对此完全被封锁。 I know what to do but I am having difficulty manipulating the tree. 我知道该怎么办,但操作树时遇到困难。

It seems like the below code works for leaf nodes but does not work for other case. 似乎以下代码适用于叶节点,但不适用于其他情况。 The following code compiles. 以下代码进行编译。 Please help. 请帮忙。

package com.binarytree;

import com.binarytree.Node;

public class BinaryTree1 {
    private Node root;
    private Node parent;

    public BinaryTree1(){
        root = null;
    }

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }

    public Node insert(int data){
        return insert(root, data);
    }

    private Node insert(Node node, int data){
        if( node == null ) {
            node = new Node(data);
        }
        else{
            if (data <= node.data){
                node.left = insert(node.left, data);
            }
            else{
                node.right = insert(node.right, data);
            }
        }

        return node;
    }

    public void printTree(Node node){
        if( node == null) return;

        //System.out.println( "left: " + (node.left != null ? node.left.data : null) );
        printTree(node.left);
        System.out.print(node.data + " ");
        //System.out.println( "right: " + (node.right != null ? node.right.data : null) );
        printTree(node.right);
    }

    /**
     * case 0: no children - leaf node - delete the parent link 
     * case 1: 1 child - make the parent to point to the node child and delete
     * case 2: find min from right sub tree, copy value in targetted node and delete duplicate node
     *          (OR)
     *         find max from left sub tree, copy value in targetted node and delete duplicate node
     * @param root
     * @param data
     */
    public Node deleteNode(Node myroot, int data){
        if( myroot == null) return null;
        else if( data < myroot.data ){ //left sub tree
            myroot.left = deleteNode(myroot.left, data);
        }
        else if (data > myroot.data){
            myroot.right = deleteNode(myroot.right, data);
        }

        else{ //found the node
            //no child
            if( myroot.left == null  && myroot.right == null ){
                myroot = null;
                parent = myroot;
            }
            else if( myroot.left == null && myroot.right != null){
                parent.right = myroot.right;    
                myroot = null;
            }
            else if (myroot.left != null && myroot.right == null){
                parent.left = myroot.right;
                myroot = null;
            } //2 children
            else{
                Node temp = myroot.right;
                myroot.data = temp.data;
                myroot.right = myroot.right.right;
            }
        }

        parent = myroot;

        return parent;
    }

}


package com.binarytree;

public class RunBinaryTree1 {
    public static void main(String[] args){
        BinaryTree1 bt = new BinaryTree1();
        bt.setRoot(bt.insert(5));
        bt.setRoot(bt.insert(3));
        bt.setRoot(bt.insert(4));
        bt.setRoot(bt.insert(1));
        bt.setRoot(bt.insert(6));
        bt.setRoot(bt.insert(9));
//      bt.setRoot(bt.insert(2));

        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.getRoot());
        System.out.println("");

        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.deleteNode(bt.getRoot(), 1));
        bt.setRoot(bt.insert(1));

        //DOES NOT WORK
        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.deleteNode(bt.getRoot(), 6));
    }
}


package com.binarytree;

public class Node {
    Node left;
    Node right;
    int data;

    public Node(int data){
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

There are three possibilities to watch out for when deleting a node from a balanced tree, which is usually the case for search trees. 从平衡树中删除节点时,需要注意三种可能,搜索树通常是这种情况。 If your trees aren't meant to be self-balancing, ignore the bits that discuss it. 如果您的树木不适合自我平衡,请忽略讨论它的内容。 Even if they are self-balancing, that particular aspect is complicated and probably worthy of a different question. 即使它们自我平衡的,该特定方面也是复杂的,可能值得提出不同的问题。

Also keep in mind the example trees below aren't actually balanced, they're just being used to show the actions. 还请记住,下面的示例树实际上并未达到平衡,它们仅用于显示操作。


First, if your node is a leaf. 首先,如果您的节点是叶子。 In that case, it's easy. 在这种情况下,这很容易。 You just delete the node. 您只需删除节点。 The transition then becomes, to delete D: 然后,过渡变成删除D:

  B             B
 / \           / \
A   C    ==>  A   C
     \
      D

If you're using balanced trees for this case, start balancing at the parent of the node you deleted (C) and work your way up the tree from there. 如果在这种情况下使用平衡树,请在删除的节点的父节点(C)上开始平衡,然后从该节点开始逐步向上平衡。


Second case, it has one child. 第二种情况,它有一个孩子。 In that case, you simply "bring" that child up, pointers and all. 在这种情况下,您只需“抚养”那个孩子,指针和其他所有东西。 For example, deleting C in the following: 例如,在下面删除C:

  B             B
 / \           / \
A   C    ==>  A   D
     \             \
      D             E
       \
        E

If the tree is self-balancing, you would start at the node you shifted up in to, D in this case. 如果树是自平衡的,则将从上移到的节点开始,在这种情况下为D。


The third case is a little trickier in that the node you're deleting has two children so you can neither delete it nor bring up a child node. 第三种情况有些棘手,因为您要删除的节点有两个子节点,因此您既不能删除它也不能调出子节点。

What you do in that case is to swap the data in that node with the data of its immediate predecessor, which is guaranteed to be either a leaf node or a node with a left child only. 在这种情况下,您要做的是将该节点中的数据与其前身的数据交换,这保证是叶节点或仅具有左子节点的节点。

Then you simply revert back to case 1 or 2 above and delete the predecessor node (which now contains the data you want to remove) and rebalance using the appropriate rules, if desired. 然后,您可以简单地恢复到上述情况1或2,并删除先前节点(现在包含要删除的数据)并根据需要使用适当的规则进行重新平衡。

Let's say you want to delete F from the following, you first swap F with its predecessor E then delete F (from a leaf node in this case, so using case 1 above): 假设您要从以下内容中删除F,首先将F与它的前身E交换,然后删除F(在这种情况下是从叶节点开始,因此使用上面的情况1):

  B             B               B
 / \           / \             / \
A   F    ==>  A   E    ==>    A   E
   / \           / \             / \
  D   G         D   G           D   G
 / \   \       / \   \         /     \
C   E   H     C   F   H       C       H
              (swap EF)        (del F)

This works for the same reason it does in a list: 这样做的原因与在列表中的原因相同:

Index: 12345678
       ABCDEFGH

If you want to remove F from that list but the sixth position is somehow protected, you can swap the data at indexes 5 and 6: 如果要从该列表中删除F但第六位置受到某种保护,则可以在索引5和6处交换数据:

Index: 12345678
       ABCDFEGH

then delete the data at index 5: 然后删除索引5处的数据:

Index: 1234567
       ABCDEGH

The way you find the immediate predecessor of a node (with two children) is to go to it's left child then keep going right until the right child is NULL, pseudo-code such as: 找到一个节点(具有两个子节点)的直接前辈的方法是转到其左子节点,然后继续向右移动,直到右子节点为NULL,伪代码如下:

def predecessor(n):
    pre = n.left
    while pre.right != null:
        pre = pre.right
    return pre

Here is something that works. 这是可行的。 That for all the help. 那为所有帮助。

public class RunBinaryTreeForDeleteNode {
    public static void main(String[] args){
        BinaryTreeDeleteNode bt = new BinaryTreeDeleteNode();
        bt.setRoot(bt.insert(5));
        bt.setRoot(bt.insert(3));
        bt.setRoot(bt.insert(4));
        bt.setRoot(bt.insert(1));
        bt.setRoot(bt.insert(6));
        bt.setRoot(bt.insert(9));
//      bt.setRoot(bt.insert(2));

        //start of Testing deletion of nodes.
        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.getRoot());
        System.out.println("");

        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.deleteNode(bt.getRoot(), 1));
        bt.setRoot(bt.insert(1));
        System.out.println("");

        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.deleteNode(bt.getRoot(), 6));
        bt.setRoot(bt.insert(6));
        System.out.println("");

        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.deleteNode(bt.getRoot(), 3));
        bt.setRoot(bt.insert(3));
        System.out.println("");

        //BELOW CODE CORRUPTS THE TREE
        System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.deleteNode(bt.getRoot(), 5));
        //bt.setRoot(bt.insert(5));
        System.out.println("");

//      System.out.print("Nodes in the BST (In order) are: "); bt.printTree(bt.getRoot());
        //System.out.println("");
        //end of Testing deletion of nodes.
    }
}




public class Node {
    Node left;
    Node right;
    int data;

    public Node(int data){
        this.data = data;
        this.left = null;
        this.right = null;
    }
}





public class BinaryTreeDeleteNode {
    private Node root;

    public BinaryTreeDeleteNode(){
        root = null;
    }

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }

    public Node insert(int data){
        return insert(root, data);
    }

    private Node insert(Node node, int data){
        if( node == null ) {
            node = new Node(data);
        }
        else{
            if (data <= node.data){
                node.left = insert(node.left, data);
            }
            else{
                node.right = insert(node.right, data);
            }
        }

        return node;
    }

    public void printTree(Node node){
        if( node == null) return;

        //System.out.println( "left: " + (node.left != null ? node.left.data : null) );
        printTree(node.left);
        System.out.print(node.data + " ");
        //System.out.println( "right: " + (node.right != null ? node.right.data : null) );
        printTree(node.right);
    }

    /**
     * case 0: no children - leaf Node - delete the parent link 
     * case 1: 1 child - make the parent to point to the Node child and delete
     * case 2: find min from right sub tree, copy value in targetted Node and delete duplicate Node
     *          (OR)
     *         find max from left sub tree, copy value in targetted BST Node and delete duplicate Node
     * @param root
     * @param data
     */
    public Node deleteNode(Node myNode, int data) {
        if( myNode == null) return null;

        Node p, p2;

        if (data < myNode.data)
        {
            myNode.left = deleteNode(myNode.left, data);
        }
        else if( data > myNode.data)
        {
            myNode.right = deleteNode(myNode.right, data);
        }
        else
        {
            if (myNode.left == null && myNode.right == null){ //leaf node
                return null;
            }
            else if (myNode.left == null) //one child
            {
                return myNode.right;
            }
            else if (myNode.right == null) //one child
            {
                return myNode.left;
            }
            else  //2 children
            {
                p2 = myNode.right;
                p = myNode.right;

                while (p.left != null){
                    p = p.left;
                }

                p.left = myNode.left;

                return p2;
            }

        }

        return myNode;
    }

}

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

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