java实现AVL树

一.各种二叉树比较

1.满二叉树

一个二叉树,每层节点都能达到最大值,即若一颗高度为h的二叉树,其节点个数为2^h-1

2.完全二叉树

若二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树

3.平衡二叉树(AVL树)

在完全二叉树的基础上实现二叉排序树

二叉排序树

二.问题引出

我们知道,数组元素创建二叉排序树时,数组第0个为根节点

例:int[] arr = {1,2,3,4,5,6};

这样构建的二叉排序树就是一个链表,这样会增加检索时间,降低效率

若把该二叉树转成AVL树则会大大提高检索效率

三.解决方案

将二叉排序树左旋转或右旋转,以达到该二叉排序树成为完全二叉树的特点

这里以该数组为例,右子树较高,故左旋

左旋步骤如下

1.创建一个新节点node,值为当前根节点的值

2.新节点的左子节点为根节点的左子节点

3.新节点的右子节点设置为根节点右子节点的左子节

4.根节点的值设为右子节点的值

5.根节点的右子节点设为右子节点的右子节点

6.根节点的左子节点设为新节点

class AVLTree{
    public static int getHeight(TreeNode root){
        //求以root为根节点树的高度
        if(root == null)
            return 0;
        return Math.max(getHeight(root.left),getHeight(root.right))+1;
    }
    public static void Rotate(TreeNode root){
        //旋转

        //右大于左
        if(getHeight(root.right)-getHeight(root.left)>1){
            if(root.right!=null&&getHeight(root.right.left)>getHeight(root.right.right)){
                rightRotate(root.right);
            }
            leftRotate(root);
        }
        //左大于右
        else if(getHeight(root.left)-getHeight(root.right)>1){

            if(root.left!=null&&getHeight(root.left.left)<getHeight(root.left.right)){
                //提前旋转一次
                leftRotate(root.left);
            }
            rightRotate(root);
        }
    }

    public static void leftRotate(TreeNode root){//左旋
        //1.创建一个新节点node,值为当前根节点的值
        TreeNode node = new TreeNode(root.val);
        //2.新节点的左子节点为根节点的左子节点
        node.left = root.left;
        //3.新节点的右子节点设置为根节点右子节点的左子节
        node.right = root.right.left;
        //4.根节点的值设为右子节点的值
        root.val = root.right.val;
        //5.根节点的右子节点设为右子节点的右子节点
        root.right = root.right.right;
        //6.根节点的左子节点设为新节点
        root.left = node;
    }
    public static void rightRotate(TreeNode root){//右旋
        TreeNode node = new TreeNode(root.val);
        node.right = root.right;
        node.left = root.left.right;
        root.val = root.left.val;
        root.left = root.left.left;
        root.right = node;
    }
}
class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(){}
    TreeNode(int val){
        this.val = val;
    }

}

二叉树是对称的,故右旋就是左旋的反过来

这里还有一个注意的点

在左旋和右旋之前,得判断一下根节点左子树和右子树的高度

以int[] arr = {10,11,7,6,8,9};为例

不管左旋还是右旋都无法形成AVL树

在右旋前应该判断左子树的左右子树,如果其右子树高度大于左子树的高度,则先将根节点的左子树进行左旋,然后再将整棵树右旋

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AVL树是一种自平衡的二叉搜索,它的升序遍历可以通过中序遍历来实现。下面是Java实现AVL树升序遍历的示例代码: ```java // AVL树节点定义 class Node { int key; int height; Node left; Node right; Node(int key) { this.key = key; this.height = 1; } } // AVL树类定义 class AVLTree { Node root; // 获取节点的高度 int getHeight(Node node) { if (node == null) { return 0; } return node.height; } // 更新节点的高度 void updateHeight(Node node) { node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1; } // 获取节点的平衡因子 int getBalanceFactor(Node node) { if (node == null) { return 0; } return getHeight(node.left) - getHeight(node.right); } // 右旋操作 Node rotateRight(Node y) { Node x = y.left; Node T2 = x.right; x.right = y; y.left = T2; updateHeight(y); updateHeight(x); return x; } // 左旋操作 Node rotateLeft(Node x) { Node y = x.right; Node T2 = y.left; y.left = x; x.right = T2; updateHeight(x); updateHeight(y); return y; } // 插入节点 Node insertNode(Node node, int key) { if (node == null) { return new Node(key); } if (key < node.key) { node.left = insertNode(node.left, key); } else if (key > node.key) { node.right = insertNode(node.right, key); } else { return node; // 不允许插入重复的节点 } updateHeight(node); int balanceFactor = getBalanceFactor(node); // 左旋操作 if (balanceFactor > 1 && key < node.left.key) { return rotateRight(node); } // 右旋操作 if (balanceFactor < -1 && key > node.right.key) { return rotateLeft(node); } // 左右旋操作 if (balanceFactor > 1 && key > node.left.key) { node.left = rotateLeft(node.left); return rotateRight(node); } // 右左旋操作 if (balanceFactor < -1 && key < node.right.key) { node.right = rotateRight(node.right); return rotateLeft(node); } return node; } // 中序遍历 void inorderTraversal(Node node) { if (node != null) { inorderTraversal(node.left); System.out.print(node.key + " "); inorderTraversal(node.right); } } } // 测试代码 public class Main { public static void main(String[] args) { AVLTree tree = new AVLTree(); tree.root = tree.insertNode(tree.root, 10); tree.root = tree.insertNode(tree.root, 20); tree.root = tree.insertNode(tree.root, 30); tree.root = tree.insertNode(tree.root, 40); tree.root = tree.insertNode(tree.root, 50); tree.root = tree.insertNode(tree.root, 25); System.out.println("AVL树的升序遍历结果:"); tree.inorderTraversal(tree.root); } } ``` 运行以上代码,输出结果为:10 20 25 30 40 50,即AVL树的升序遍历结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值