平衡二叉树AVL

平衡二叉树|B树|B+树

  • 1. 平衡二叉树
    • 1.1 如何调整最小不平衡子树
    • 1.2 左旋、右旋代码实现
    • 1.3 解决导致不平衡的四种情况
  • 2. B树|B+树
    • 2.1 2-3树

1. 平衡二叉树

  • 平衡二叉树解决了二叉排序树退化为单链表的问题;
  • 平衡二叉树也称为自平衡二叉搜索树或AVL树;
  • AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis;
  • 平衡二叉树本质还是二叉排序树;
  • 平衡二叉树的限制:空树或左右子树高度差的绝对值不超过1;
  • 平衡因子:左子树高度-右子树高度,取值范围为{-1,0,1};
  • 调整最小不平衡子树使得整个二叉排序树平衡;
  • 查找时间复杂度:O(log2n),借助递推公式:Nh=Nh-1+Nh-2+1;

平衡二叉树AVL_第1张图片
平衡二叉树AVL_第2张图片

1.1 如何调整最小不平衡子树

  • 四种不平衡子树:LL、LR、RL、RR,分别表示1)在root树的左子节点的左子树插入节点导致不平衡;1)在root树的左子节点的右子树插入节点导致不平衡;1)在root树的右子节点的左子树插入节点导致不平衡;1)在root树的右子节点的右子树插入节点导致不平衡;
    平衡二叉树AVL_第3张图片
  • LL、RR为两种基本情况,对应解决方案为单旋转,分别为:右旋、左旋;
    LL:树右旋
    平衡二叉树AVL_第4张图片
    RR:树左旋
    平衡二叉树AVL_第5张图片
  • LR、RL为两种复杂情况,对应解决方案为双旋转,分别为:先左旋再右旋、先右旋再左旋;
    LR:左子树左旋+树右旋
    平衡二叉树AVL_第6张图片

平衡二叉树AVL_第7张图片
RL:右子树右旋+树左旋
平衡二叉树AVL_第8张图片
平衡二叉树AVL_第9张图片

1.2 左旋、右旋代码实现

左旋:
平衡二叉树AVL_第10张图片

/**
* 左旋
*/
private void leftRotate() {
	// 1.创建新节点,与当前根节点值一致
	TreeNode newNode = new TreeNode(val);
	// 2.新节点的左子树为root的左子树
	newNode.left=left;
	// 3. 新节点的右子树为root的右子树的左子树
	newNode.right=right.left;
	// 4.root的值替换为其右子节点的值
	val=right.val;
	// 5.root的右子树为右子树的右子树
	right=right.right;
	// 6.当前节点的左子树为新节点
	left=newNode;
}

右旋:
平衡二叉树AVL_第11张图片

/**
 * 右旋
 */
private void rightRotate() {
    // 1.创建新节点,与当前根节点值一致
    TreeNode newNode = new TreeNode(val);
    // 2.新节点的右子树为root的右子树
    newNode.right=right;
    // 3. 新节点的左子树为root的左子树的右子树
    newNode.left=left.right;
    // 4.root的值替换为其左子节点的值
    val=left.val;
    // 5.root的左子树为左子树的左子树
    left=left.left;
    // 6.当前节点的右子树为新节点
    right=newNode;
}

1.3 解决导致不平衡的四种情况

class AVLTree{
    public TreeNode root;

    public AVLTree(TreeNode root){
        this.root=root;
    }

    public AVLTree() {

    }


    /**
     * 插入节点
     */
    public void insert(TreeNode node){
        // 根节点
        if (root==null){
            root=node;
        }else{
            root.insert(node);
        }
    }

    /**
     * 中序遍历
     */
    public void inOrder(){
        if (root==null){
            return;
        }
        root.inOrder();
    }

    /**
     * 层序遍历
     */
    public void levelOrder(){
        if (root==null){
            return;
        }
        root.levelOrder();
    }
}

class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int val){
        this.val=val;
    }

    public TreeNode(int val,TreeNode left,TreeNode right){
        this.val=val;
        this.left=left;
        this.right=right;
    }

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

    /**
     * 返回以当前节点左子树的高度
     * @return
     */
    public int getLeftHeight(){
        if (left==null){
            return 0;
        }
        return left.getHeight();
    }

    /**
     * 返回以当前节点右子树的高度
     * @return
     */
    public int getRightHeight(){
        if (right==null){
            return 0;
        }
        return right.getHeight();
    }

    @Override
    public String toString() {
        return "TreeNode{" +
                "val=" + val +
                '}';
    }

    /**
     * 新增节点,满足二叉排序树要求
     * @param node
     */
    public void insert(TreeNode node) {
        if (node==null){
            return;
        }

        // 比较当前节点与node节点的大小关系
        if (node.val<val){
            if (left==null){
                left=node;
            }else{
                left.insert(node);
            }
        }else{
            if (right==null){
                right=node;
            }else{
                right.insert(node);
            }
        }

        // 左旋:右子树高度过大
        if (getRightHeight()-getLeftHeight()>1){
            // RR:右子树的右子树上插入节点导致不平衡
            if (right.getRightHeight()-right.getLeftHeight()>=1){
                leftRotate();
            }else if (right.getLeftHeight()-right.getRightHeight()>=1){ // RL:右子树的左子树上插入节点导致不平衡
                // 右子树进行右旋
                right.rightRotate();
                // 整棵树左旋
                leftRotate();
            }
        }else if (getLeftHeight()-getRightHeight()>1){ // 右旋:左子树高度过大
            // LL:左子树的左子树上插入节点导致不平衡
            if (left.getLeftHeight()-left.getRightHeight()>=1){
                rightRotate();
            }else if (left.getRightHeight()-left.getLeftHeight()>=1){ // LR:右左子树的右子树上插入节点导致不平衡
                // 左子树进行左旋
                left.leftRotate();
                // 整棵树右旋
                rightRotate();
            }
        }
    }

    /**
     * 左旋
     */
    private void leftRotate() {
        // 1.创建新节点,与当前根节点值一致
        TreeNode newNode = new TreeNode(val);
        // 2.新节点的左子树为root的左子树
        newNode.left=left;
        // 3. 新节点的右子树为root的右子树的左子树
        newNode.right=right.left;
        // 4.root的值替换为其右子节点的值
        val=right.val;
        // 5.root的右子树为右子树的右子树
        right=right.right;
        // 6.当前节点的左子树为新节点
        left=newNode;
    }

    /**
     * 右旋
     */
    private void rightRotate() {
        // 1.创建新节点,与当前根节点值一致
        TreeNode newNode = new TreeNode(val);
        // 2.新节点的右子树为root的右子树
        newNode.right=right;
        // 3. 新节点的左子树为root的左子树的右子树
        newNode.left=left.right;
        // 4.root的值替换为其左子节点的值
        val=left.val;
        // 5.root的左子树为左子树的左子树
        left=left.left;
        // 6.当前节点的右子树为新节点
        right=newNode;
    }

    /**
     * 中序遍历
     */
    public void inOrder(){
        if (left!=null){
            left.inOrder();
        }
        System.out.println("node:"+val);
        if (right!=null){
            right.inOrder();
        }
    }

    /**
     * 层序遍历
     */
    public void levelOrder() {
        Deque<TreeNode> queue=new ArrayDeque<>();
        queue.offer(this);

        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();
            System.out.println("node:"+cur.val);

            if (cur.left!=null){
                queue.offer(cur.left);
            }
            if (cur.right!=null){
                queue.offer(cur.right);
            }
        }
    }
}

2. B树|B+树

  • 二叉树实现简单,但由于其可能拥有极深的高度,往往实用价值不高;
  • n叉树的提出解决了二叉树的高度问题,可以降低二叉树高度;
  • n叉树:一个节点可以拥有两个以上的子节点的树称为n叉树;
  • 典型的n叉树:红黑树、2-3树、2-3-4树、B树;
    平衡二叉树AVL_第12张图片
    平衡二叉树AVL_第13张图片
    平衡二叉树AVL_第14张图片

平衡二叉树AVL_第15张图片
平衡二叉树AVL_第16张图片

平衡二叉树AVL_第17张图片
平衡二叉树AVL_第18张图片
平衡二叉树AVL_第19张图片
平衡二叉树AVL_第20张图片

平衡二叉树AVL_第21张图片

平衡二叉树AVL_第22张图片
平衡二叉树AVL_第23张图片

2.1 2-3树

  • 本质仍为排序树,需满足左<根<右的特点;
  • 2-3树由2节点、3节点构成;
  • 三叉B树;

平衡二叉树AVL_第24张图片
平衡二叉树AVL_第25张图片
资料来源:1)尚硅谷;2)王道考研

你可能感兴趣的:(Java开发,数据结构与算法,数据结构,算法,b树)