数据结构与算法(二十)

版权声明:版权由我个人所有,未经允许不得用于除学习外的其他用途,望周知。 https://blog.csdn.net/weixin_44515563/article/details/89328864

二叉排序树 左旋转 右旋转

单旋转:1左旋转2右旋转 双向旋转: 调整排序树,使其最优。(左子树和右子树的高度差的绝对值不大于1)

平衡二叉树

在这里插入图片描述
在这里插入图片描述

Node类

package com.bjsxt.BinarySortTree;
//二叉排序树
public class Node {
    int value;
    Node left;
    Node right;

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

    /**
     * 获取左子树的高度
     * @return
     */
    public int leftHeight(){
        if(left==null){
            return 0;
        }
        return left.height();
    }

    /**
     * 获取右子树的高度
     * @return
     */
    public int rightHeight(){
        if(right==null){
            return 0;
        }
        return right.height();
    }

    /**
     * 返回当前节点的高度
     * @return
     */
    public int height(){
        return Math.max(left==null?0:left.height(),right==null?0:right.height())+1;
    }


    /**
     * 向子树中添加节点
     * @param node
     */
    public void add(Node node){
        if(node==null){
            return;
        }
        //判断传入的节点的值比当前子树的根节点的值大还是小
        //添加的节点比当前节点的值更小
        if(node.value<this.value){
            //如果左节点为空
            if(this.left==null){
                this.left=node;
                //如果不为空
            }else{
                this.left.add(node);
            }
        }else {
            if(this.right==null){
                this.right=node;
            }else{
                this.right.add(node);
            }
        }
        //查询是否是平衡
        //进行右旋转
        if(leftHeight()-rightHeight()>=2){
            //双旋转
            if(left!=null&&left.leftHeight()<left.rightHeight()){
                //先左旋转
                left.leftRotate();
                //再右旋转
                rightRotatr();
                //单旋转
            }else{
                rightRotatr();
            }
            //左旋转
            if(leftHeight()-rightHeight()<=-2){
                //双旋转
                if(right!=null&&right.rightHeight()<right.leftHeight()){
                    right.rightRotatr();
                    leftRotate();
                //单旋转
                }else{
                    leftRotate();
                }
            }
        }
    }

    /**
     * 左旋转
     */
    private void leftRotate() {
        Node newLeft = new Node(value);
        newLeft.left=left;
        newLeft.right=right.left;
        value=right.value;
        right=right.right;
        left=newLeft;
    }

    /**
     * 右旋转
     */
    private void rightRotatr(){
        //创建一个新的节点,值等于当前节点的值
        Node newRight = new Node(value);
        //把新节点的右子树设置为当前节点的右子树
        newRight.right=right;
        //把新节点的左子树设置为当前节点左子树的右子树
        newRight.left=left.right;
        //把当前节点的值换为左子节点的值
        value=left.value;
        //把当前节点的左子树设置为左子树的左子树
        left=left.left;
        //把当前节点的右子树设置为新节点
        right=newRight;
    }

    /**
     *中序遍历二叉排序树,从小到大排序
     * @param node
     */
    public void midShow(Node node) {
        if (node==null){
            return;
        }
        midShow(node.left);
        System.out.println(node.value);
        midShow(node.right);
    }

    /**
     * 查找节点
     * @param value
     */
    public Node search(int value) {
        if(this.value==value){
            return this;
        }else if(value<this.value){
            if(left==null){
                return null;
            }
            return left.search(value);
        }else {
            if(right==null){
                return null;
            }
            return right.search(value);
        }
    }

    /**
     * 搜索父节点
     * @param value
     * @return
     */
    public Node searchParent(int value) {
        if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)){
            return this;
        }else{
            if(this.value>value&&this.left!=null){
                return this.left.searchParent(value);
            }else if(this.value<value&&this.right!=null){
                return this.right.searchParent(value);
            }
            return null;
        }
    }
}

创建一颗二叉排序树

package com.bjsxt.BinarySortTree;

public class BinarySortTree {
    Node root;

    public void add(Node node){
        //如果是一颗空树
        if(root==null){
            root=node;
        }else{
            root.add(node);
        }
    }

    /**
     * 中序遍历二叉排序树,从小到大排序
     */
    public void midShow(){
        if(root!=null){
            root.midShow(root);
        }
    }

    /**
     * 节点的查找
     * @param value
     * @return
     */
    public Node search(int value){
        if(root==null){
            return null;
        }else{
            return root.search(value);
        }
    }

    /**
     * 删除节点
     * @param value
     */
    public void delete(int value){
        if(root==null){
            return;
        }else {
            //找到这个节点
            Node target = search(value);
            if(target==null){
                return;
            }
            //找到他的父节点
            Node parent = seaechParent(value);
            //要删除的节点是叶子节点
            if(target.left==null&&target.right==null){
                //要删除的节点是父节点的左子节点
                if(parent.left.value==value){
                    parent.left=null;
                    //要删除的节点是父节点的右子节点
                }else {
                    parent.right=null;
                }
                //要删除的节点有两个子节点的情况
            }else  if(target.left!=null&&target.right!=null){
                //删除右子树中最小的节点,并获取到该节点的值
                int min = deleteMin(target.right);
                //替换目标节点中的值
                target.value=min;
                //要删除的节点有一个左子节点或右子节点
            }else {
                //有左子节点
                if(target.left!=null){
                    //要删除的节点是父节点的左子节点
                    if(parent.left.value==value){
                        parent.left=target.left;
                        //要删除的节点是父节点的右子节点
                    }else {
                        parent.right=target.left;
                    }
                    //有右子节点
                }else {
                    //要删除的节点是父节点的左子节点
                    if(parent.left.value==value){
                        parent.left=null;
                        //要删除的节点是父节点的右子节点
                    }else {
                        parent.right=null;
                    }
                }
            }
        }
    }

    /**
     * 删除一棵树中最小的节点
     * @param node
     * @return
     */
    private int deleteMin(Node node) {
        Node target = node;
        //递归向左找
        while(target.left!=null){
            target=target.left;
        }
        //删除最小的这个节点
        delete(target.value);
        return target.value;
    }

    /**
     * 搜索父节点
     * @param value
     * @return
     */
    public Node seaechParent(int value){
        if(root==null){
            return null;
        }else {
            return root.searchParent(value);
        }

    }
}



测试类(单旋转,双旋转)

package com.bjsxt.BinarySortTree;

public class TestBibarySortTree {
    public static void main(String[] args){
//        int[] arr=new int[]{8,9,6,7,5,4};
//        int[] arr=new int[]{2,1,4,3,5,6};
        int[] arr=new int[]{8,9,5,4,6,7};
        //创建一颗二叉排序树
        BinarySortTree bst = new BinarySortTree();
        //循环结构
        for(int i:arr){
            bst.add(new Node(i));
        }
        //查看高度
        System.out.println(bst.root.height());

        System.out.println(bst.root.value);

//        System.out.println(bst.root.leftHeight());
//        System.out.println(bst.root.rightHeight());
    }
}

该代码测试结果

3
6

猜你喜欢

转载自blog.csdn.net/weixin_44515563/article/details/89328864