繁体   English   中英

删除二叉搜索树中的节点

[英]Deleting an node in 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;
    }
}

从平衡树中删除节点时,需要注意三种可能,搜索树通常是这种情况。 如果您的树木不适合自我平衡,请忽略讨论它的内容。 即使它们自我平衡的,该特定方面也是复杂的,可能值得提出不同的问题。

还请记住,下面的示例树实际上并未达到平衡,它们仅用于显示操作。


首先,如果您的节点是叶子。 在这种情况下,这很容易。 您只需删除节点。 然后,过渡变成删除D:

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

如果在这种情况下使用平衡树,请在删除的节点的父节点(C)上开始平衡,然后从该节点开始逐步向上平衡。


第二种情况,它有一个孩子。 在这种情况下,您只需“抚养”那个孩子,指针和其他所有东西。 例如,在下面删除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

这是可行的。 那为所有帮助。

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