码迷,mamicode.com
首页 > 其他好文 > 详细

平衡二叉树

时间:2021-02-20 12:44:09      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:代码实现   enc   closed   nta   fence   line   pen   lazy   常见   

1、平衡二叉树出现的原因

  • 二叉排序树的弊端

    • 数列:1,2,3,4,5,6

    • 创建出来的二叉排序树为:

      技术图片

2、平衡二叉树概念

  • 平衡二叉搜索树

  • AVL树

  • 保证查询效率最高

  • 一颗空树或者是一颗左右两颗子树的高度差的绝对值不超过1, 并且左右子树分别也是平衡二叉树的树

2.1、二叉树结点

技术图片
// 树结点
private static class TreeNode{
?
    int val;
    TreeNode left;
    TreeNode right;
?
    public TreeNode(int val) {
        this.val = val;
    }
}
View Code
 

2.2.1、结点中求高度的方法

技术图片
// 返回结点的高度
public int height(){
    return Math.max(left == null ? 0 : left.height(), right == null? 0 : right.height()) + 1;
}
?
// 返回左子树的高度
public int leftHeight(){
    if (left == null){
        return 0;
    }
    return left.height();
}
?
// 返回右子树的高度
public int rightHeight(){
    if (right == null){
        return 0;
    }
    return right.height();
}
View Code
 

2.2.2、结点中添加结点方法

技术图片
// 根据二叉排序树的规则添加结点
public void add(TreeNode newNode){
?
    if (newNode == null){
        return ;
    }
?
    /**
         * 如果当前新结点的值大于当前结点this
         *      如果当前结点右子树为空,直接添加
         *      否则,右子树重新调用add方法,重复此步骤
         */
    if (newNode.val >= this.val){
        if (this.right == null){
            this.right = newNode;
        }else {
            this.right.add(newNode);
        }
    }else {
        if (this.left == null){
            this.left = newNode;
        }else {
            this.left.add(newNode);
        }
    }
}
View Code
 

2.2、平衡二叉树

技术图片
private static class AVL{
?
    // 根节点
    private TreeNode root;
?
}
View Code
 

2.2.1、平衡二叉树中求高度的方法

技术图片
// 返回左子树高度
public int leftHeight(TreeNode node){
    if (node == null){
        return 0;
    }
    return node.leftHeight();
}
?
// 返回右子树高度
public int rightHeight(TreeNode node) {
    if (node == null) {
        return 0;
    }
    return node.rightHeight();
}
?
// 返回树的高度
public int height(TreeNode node){
    if (node == null) {
        return 0;
    }
    return node.height();
}
View Code
技术图片
// 返回左子树高度
public int leftHeight(TreeNode node){
    if (node == null){
        return 0;
    }
    return node.leftHeight();
}
?
// 返回右子树高度
public int rightHeight(TreeNode node) {
    if (node == null) {
        return 0;
    }
    return node.rightHeight();
}
?
// 返回树的高度
public int height(TreeNode node){
    if (node == null) {
        return 0;
    }
    return node.height();
}
View Code
 

2.2.2、平衡二叉树中添加结点方法

技术图片
// 添加结点
public void add(TreeNode node){
    // root为空,说明node为构建树的第一个结点
    if (root == null){
        root = node;
    }else {
        root.add(node);
    }
}
View Code
 

3、平衡二叉树左旋

  • 数列4,3,6,5,7,8

3.1、示意图

技术图片

3.2、代码

技术图片
public void leftRotate(){
?
    // 1、创建一个新结点,值为当前结点的值
    TreeNode newNode = new TreeNode(val);
    // 2、新结点的左子树  设置为  当前结点的左子树
    newNode.left = left;
    // 3、新结点的右子树  设置为  当前结点右子结点的左子树
    newNode.right = right.left;
    // 4、把当前结点的值  设置为  当前结点 右子节点的值
    val = right.val;
    // 5、把当前结点的右子树  设置为  右子节点 的右子树
    right = right.right;
    // 6、把当前结点的左子树  设置为  新结点
    left = newNode;
?
}
View Code
 

4、平衡二叉树右旋

  • 数列10,12,8,9,7,6

4.1、示意图

技术图片

4.2、代码

技术图片
public void rightRotate(){
?
    // 1、创建一个新结点,值为当前结点
    TreeNode newNode = new TreeNode(val);
    // 2、把新结点的右子树  设置为  当前结点的右子树
    newNode.right = right;
    // 3、把新结点的左子树  设置为  当前结点的左子树的右子树
    newNode.left = left.right;
    // 4、把当前结点的值  设置为  当前结点的左子结点的值
    val = left.val;
    // 5、把当前结点的左子树  设置为  当前结点的左子结点的左子树
    left = left.left;
    // 6、把当前结点的右子树  设置为  新结点
    right = newNode;
?
}
View Code
 

5、双旋

5.1、单次右旋转失败

  • 数列10,11,7,6,8,9

    技术图片

5.2、单次右旋失败原因

  • 根节点的左子节点的 右子树的高度 大于 左子树的高度

  • 根节点的左子节点的 右子树的高度 = 2

  • 根节点的左子节点的 左子树的高度 = 1

5.3、单次右旋失败解决方案

  • 先对根节点的左子树进行 左旋转

  • 再对根节点进行 右旋转

    技术图片

5.4、单次左旋失败

  • 数列2,1,6,5,7,3

    技术图片

5.5、单次左旋失败原因

  • 根节点的右子结点左子树的高度 大于 右子树的高度

  • 根节点的右子结点的 左子树的高度 = 3

  • 根节点的右子结点的 右子树的高度 = 1

5.6、单次左旋失败解决方案

  • 先对根节点的右子节点进行右旋转

  • 再对根节点进行左旋转

    技术图片

5.7、判断在添加结点时是否需要进行左旋右旋的代码

技术图片
// 左旋
if((rightHeight() - leftHeight()) > 1){
    // 判定当前节点的右子节点的  左子树的高度  是否大于  右子树的高度
    if (right.leftHeight() > right.rightHeight()){
        right.rightRotate();
    }
    leftRotate();
}
?
// 右旋
if (leftHeight() - rightHeight() > 1){
    // 判定当前结点左子结点的  右子树的高度  是否大于  左子树的高度
    if(left != null && left.rightHeight() > left.leftHeight()){
        // 对当前结点的左子树进行左旋转
        left.leftRotate();
    }
    rightRotate();
}
View Code
 

6、平衡二叉树的代码实现

public class AVLTree {
?
    // 树结点
    private static class TreeNode{
?
        int val;
        TreeNode left;
        TreeNode right;
?
        public TreeNode(int val) {
            this.val = val;
        }
?
        // 返回结点的高度
        public int height(){
            return Math.max(left == null ? 0 : left.height(), right == null? 0 : right.height()) + 1;
        }
?
        // 返回左子树的高度
        public int leftHeight(){
            if (left == null){
                return 0;
            }
            return left.height();
        }
?
        // 返回右子树的高度
        public int rightHeight(){
            if (right == null){
                return 0;
            }
            return right.height();
        }
?
        // 左旋
        public void leftRotate(){
?
            // 1、创建一个新结点,值为当前结点的值
            TreeNode newNode = new TreeNode(val);
            // 2、新结点的左子树  设置为  当前结点的左子树
            newNode.left = left;
            // 3、新结点的右子树  设置为  当前结点右子结点的左子树
            newNode.right = right.left;
            // 4、把当前结点的值  设置为  当前结点 右子节点的值
            val = right.val;
            // 5、把当前结点的右子树  设置为  右子节点 的右子树
            right = right.right;
            // 6、把当前结点的左子树  设置为  新结点
            left = newNode;
?
        }
?
        // 右旋
        public void rightRotate(){
?
            // 1、创建一个新结点,值为当前结点
            TreeNode newNode = new TreeNode(val);
            // 2、把新结点的右子树  设置为  当前结点的右子树
            newNode.right = right;
            // 3、把新结点的左子树  设置为  当前结点的左子树的右子树
            newNode.left = left.right;
            // 4、把当前结点的值  设置为  当前结点的左子结点的值
            val = left.val;
            // 5、把当前结点的左子树  设置为  当前结点的左子结点的左子树
            left = left.left;
            // 6、把当前结点的右子树  设置为  新结点
            right = newNode;
        }
?
        // 根据二叉排序树的规则添加结点
        public void add(TreeNode newNode){
?
            if (newNode == null){
                return ;
            }
?
            /**
             * 如果当前新结点的值大于当前结点this
             *      如果当前结点右子树为空,直接添加
             *      否则,右子树重新调用add方法,重复此步骤
             */
            if (newNode.val >= this.val){
                if (this.right == null){
                    this.right = newNode;
                }else {
                    this.right.add(newNode);
                }
            }else {
                if (this.left == null){
                    this.left = newNode;
                }else {
                    this.left.add(newNode);
                }
            }
?
            // 左旋
            if((rightHeight() - leftHeight()) > 1){
                // 判定当前节点的右子节点的  左子树的高度  是否大于  右子树的高度
                if (right.leftHeight() > right.rightHeight()){
                    right.rightRotate();
                }
                leftRotate();
            }
?
            // 右旋
            if (leftHeight() - rightHeight() > 1){
                // 判定当前结点左子结点的  右子树的高度  是否大于  左子树的高度
                if(left != null && left.rightHeight() > left.leftHeight()){
                    // 对当前结点的左子树进行左旋转
                    left.leftRotate();
                }
                rightRotate();
            }
        }
?
    }
?
    // AVL树
    private static class AVL{
?
        // 根节点
        private TreeNode root;
?
        // 添加结点
        public void add(TreeNode node){
            // root为空,说明node为构建树的第一个结点
            if (root == null){
                root = node;
            }else {
                root.add(node);
            }
        }
?
        // 返回左子树高度
        public int leftHeight(TreeNode node){
            if (node == null){
                return 0;
            }
            return node.leftHeight();
        }
?
        // 返回右子树高度
        public int rightHeight(TreeNode node) {
            if (node == null) {
                return 0;
            }
            return node.rightHeight();
        }
?
        // 返回树的高度
        public int height(TreeNode node){
            if (node == null) {
                return 0;
            }
            return node.height();
        }
?
    }
?
}

 

 



平衡二叉树

标签:代码实现   enc   closed   nta   fence   line   pen   lazy   常见   

原文地址:https://www.cnblogs.com/LittleSkinny/p/14419452.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!