二叉排序树


声明:下面的代码只是一个最基础的实现,没有经过严格的测试。

/**
 * 二叉排序树(BST)
 * 定义:对于任何一个非叶子节点,要求左子节点的值比父节点小,右子节点的值比父节点值大。如果有相同的值,可以在
 * 左节点或者右节点
 */
public class BinarySortTree {
    public Node root;

    public static void main(String[] args) {
        BinarySortTree tree = new BinarySortTree();
        int[] arr={4,7,2,1,5,5,0};
        for (int i : arr) {
            tree.addNode(i);
        }
        tree.deleteNode(5);
        tree.infixOrder();
        //System.out.println(tree.searchParent(7));
    }
    public void addNode(int value){
        if(root == null){
            root = new Node(value);
        }else {
            addNode(root,value);
        }
    }

    public Node search(int value){
        return  search(root,value);
    }
    public Node searchParent(int value){
        if(root == null){
            return null;
        }
        if(root.value == value){
            return null;
        }
        return searchParent(root,value);
    }

    /**
     * 删除节点,分三种情况:1,待删除节点是叶子节点。2,待删除节点只有一棵子树。3,待删除节点既有左子节点又有右子节点
     * @param value 待删除的节点
     */
    public void deleteNode(int value){
        if(root == null){
            return;
        }
        Node parent = searchParent(value);
        Node node = search(value);

        //第一种情况:待删除的节点是叶子节点
        if(node.left == null && node.right == null){
            if(parent.left != null && parent.left.value == value){
                parent.left = null;
            }
            if(parent.right != null && parent.right.value == value){
                parent.right = null;
            }
            node = null;
            return;
        }
        // 第二种情况:待删除的节点只有一棵子树(左子树或右子树的情况)
        if(node.left !=null && node.right == null){
            if(parent.left.value == value){
                parent.left=node.left;
            }else if(parent.right.value == value){
                parent.right=node.left;
            }
            node = null;
            return;
        }else  if(node.right !=null && node.left == null){
            if(parent.left.value == value){
                parent.left=node.right;
            }else if(parent.right.value == value){
                parent.right=node.right;
            }
            node = null;
            return;
        }

        //第二种情况:待删除的节点既有左子树又有右子树的情况)
        /**
         * 两种处理方式:寻找待删除节点右子树中的最小节点或者左子树的最大节点,将该节点的值赋给待删除节点并删除该节点即可
         * 中序遍历中:右子树的最小节点即该节点的后继节点。左子树的最大节点即该节点的前驱节点。
         * 有后继节点或者前驱节点代替该节点,然后删除后继结点或者前驱节点
         */
        if(node.left != null && node.right != null){
            int v = delRightTreeMin(node);
            node.value=v;
        }

    }

    //以node节点作为根节点,寻找右子树的最小值节点。删除该节点并返回该节点的值
    //也可以寻找左子树的最大节点,一样的
    private int delRightTreeMin(Node node){
        Node tempNode=node.right;
        while (tempNode.left != null){
            tempNode=tempNode.left;
        }
        int value = tempNode.value;
        deleteNode(value);
        return value;
    }

    // 对于二叉排序树,中序遍历时输出的值 是 升序排列的
    public void infixOrder(){
        if(root != null){
            infixOrder(root);
        }else{
            System.out.println("该二叉树为空");
        }
    }

    //递归查找父节点
    private Node searchParent(Node curNode,int value){
        if(curNode.left != null ){
            if(curNode.left.value == value){
                return curNode;
            }else{
                Node node = searchParent(curNode.left,value);
                if(node != null){
                    return node;
                }
            }
        }
        if(curNode.right != null ){
            if(curNode.right.value == value){
                return curNode;
            }else{
                Node node = searchParent(curNode.right,value);
                if(node != null){
                    return node;
                }
            }
        }

        return null;

    }
    //使用递归的方式查找node
    private Node search(Node curNode,int value){
        if(curNode.value == value){
            return curNode;
        }
        if(curNode.left != null){
            Node node=search(curNode.left,value);
            if(node != null){
                return node;
            }
        }

        if(curNode.right != null){
            Node node=search(curNode.right,value);
            if(node != null){
                return node;
            }
        }
        return null;
    }
    //中序遍历,先左节点再父节点,后右节点
    private void infixOrder(Node node){
        if(node==null){
            return;
        }

        //每次都是先输出父节点
        if(node.left!=null){
            infixOrder(node.left);
        }
        System.out.println(node);
        if(node.right!=null){
            infixOrder(node.right);
        }
    }

    /**
     * 使用递归的方式新增元素:按照二叉排序树的定义,如果待插入的值比父节点小,则作为左节点。反之则为右节点。
     * 值插入的逻辑:先从根节点开始,插入的值和根节点的值比较大小,放到合适的位置。如果根节点有左节点或右节点,那么根节点
     * 的左节点或者有节点作为新的父节点,继续和待插入的值比较。直至父节点为null。
     * @param parentNode  待插入节点的父节点
     * @param value 待插入的值
     */
    private void addNode(Node parentNode,int value){
        if(parentNode == null){
            return;
        }
        if(value < parentNode.value ){
            if(parentNode.left == null){
                parentNode.left=new Node(value);
            }else{
                //如果父节点存在左节点,那么该左节点作为新的父节点进行递归
                addNode(parentNode.left,value);
            }
        }

        if(value >= parentNode.value){
            if(parentNode.right == null){
                parentNode.right=new Node(value);
            }else{
                //如果父节点存在右节点,那么该右节点作为新的父节点进行递归
                addNode(parentNode.right,value);
            }
        }
    }


    class Node{
        //value
        private Integer value;
        //左节点
        public Node left;
        //右节点
        public Node right;

        public Node(Integer value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "value=" + value +
                    '}';
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值