删除二进制搜索树中的节点

时间:2014-09-23 05:13:52

标签: java binary-search-tree

这不是作业。我完全被封锁了。我知道该怎么做但我操作树很困难。

以下代码似乎适用于叶节点,但不适用于其他情况。以下代码编译。请帮忙。

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;
    }
}

2 个答案:

答案 0 :(得分:2)

从平衡树中删除节点时,有三种可能需要注意,这通常是搜索树的情况。如果你的树不是自平衡的,那就忽略讨论它的部分。即使他们 自我平衡,这个特定的方面也很复杂,可能值得一个不同的问题。

另请注意,下面的示例树并非实际平衡,它们仅用于显示操作。


首先,如果您的节点是叶子。在这种情况下,这很容易。您只需删除该节点。然后转换为删除D:

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

如果您在这种情况下使用平衡树,请在您删除的节点(C)的父节点处开始平衡,然后从那里开始向上工作。


第二种情况,它有一个孩子。在这种情况下,你只需&#34;带来&#34;那孩子,指针和所有。例如,删除以下内容中的C:

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

如果树是自平衡的,那么你将从你向上移动的节点开始,在这种情况下为D.


第三种情况有点棘手,因为您要删除的节点有两个子节点,因此您既不能删除它也不能启动子节点。

在这种情况下,您要做的是将该节点中的数据与其前一个数据进行交换,该数据保证为叶子节点或仅具有左子节点的节点。

然后,您只需返回上面的案例1或2并删除前任节点(现在包含您要删除的数据),并根据需要使用适当的规则进行重新平衡。

假设您要从以下内容中删除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)

这与其在列表中的原因相同:

Index: 12345678
       ABCDEFGH

如果要从该列表中删除F但第六个位置以某种方式受到保护,则可以在索引5和6处交换数据:

Index: 12345678
       ABCDFEGH

然后删除索引5处的数据:

Index: 1234567
       ABCDEGH

找到节点的前任(有两个孩子)的方式是去左边的孩子,然后继续向右走,直到右边的孩子为NULL,伪代码如:

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

答案 1 :(得分:0)

这是有效的。这对所有的帮助。

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;
    }

}