AVL平衡二叉树(java)

AVL平衡二叉树

引入

因为二叉搜索树不存在平衡算法,所以在某些特殊的情况下,二叉搜索树等同于线性,出现蹩脚的情况,设计者们发现降低树的高度自然就可以提高查找效率。那么如何解决降低树的高度的问题?在这种基础上设计者给二叉树加入了平衡算法,出现了平衡树。

在这里插入图片描述

我们来看一下avl树的左旋过程

在这里插入图片描述

首先我们将处理左旋的代码注释掉 看一下结果

package com.zyk;


class Node{
    int value;
    Node left;
    Node right;

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


    //添加节点的方法
    public void add(Node node){
        if(node==null){
            return;
        }

        if(node.value<this.value){
            if(this.left==null){
                this.left=node;
            }else{
                //递归让该节点的左子节点去执行add方法
                this.left.add(node);
            }
        }

        if(node.value>this.value){
            if(this.right ==null){
                this.right =node;
            }else{
                //递归让该节点的右子节点去执行add方法
                this.right.add(node);
            }
        }

        /*
        if(rightHeight()-leftHeight()>1){
            leftRotated();
        }*/
    }

    //中序遍历输出结果
    public void inorder(){
        if(this.left!=null) {
            this.left.inorder();
        }
        System.out.print(this.value+"\t");
        if(this.right !=null){
            this.right.inorder();
        }
    }

    //返回以该节点为根节点的树的高度(包括该节点)
    public int heigth(){
        return Math.max(left==null?0:left.heigth(), right ==null?0: right.heigth())+1;
    }

    //返回左子树的高度
    public int leftHeight(){
        if(left==null){
            return 0;
        }else{
            return left.heigth();
        }
    }

    //返回右子树的高度
    public int rightHeight(){
        if(right ==null){
            return 0;
        }else{
            return right.heigth();
        }
    }

    //左旋的方法
    private void leftRotated(){
        //创建新的节点 使新节点的值等于当前根节点的值
        Node newNode = new Node(value);
        //让新的节点的左子节点指向当前根节点的左子节点
        newNode.left=left;
        //让新的节点的右子节点指向当前根节点的右子树的左子节点
        newNode.right=right.left;
        //把当前跟节点的值设置为当前跟节点右子节点的值
        value=right.value;
        //把当前跟节点的右子节点的右子树挂到当前根节点
        right=right.right;
        //把当前节点的左子节点设置成为新的节点
        left=newNode;
    }
}

class AVLTree{
    private Node root;

    public Node getRoot(){
        return root;
    }

    public void add(Node node){
        if(root==null){
            root=node;
        }else{
            //每一个node都要去跟root比较
            root.add(node);
        }
    }

    public void inorder(){
        if(root!=null){
            root.inorder();
        }
    }
}
public class AVLTreeDemo {
    public static void main(String[] args) {
        int[] arr={4,3,6,5,7,8};
        AVLTree avlTree=new AVLTree();
        for (int i = 0; i <arr.length ; i++) {
            avlTree.add(new Node(arr[i]));
        }
        //中序结果是
        System.out.println("中序结果是");
        avlTree.inorder();
        System.out.println();
        //在没有处理平衡前
        System.out.println("在没有处理平衡前");
        System.out.println("root的左子树高度"+avlTree.getRoot().leftHeight());
        System.out.println("root的右子树高度"+avlTree.getRoot().rightHeight());
        System.out.println("右子树高度大于左子树高度进行左旋处理");
    }
}

中序结果是
3	4	5	6	7	8	
在没有处理平衡前
root的左子树高度1
root的右子树高度3
右子树高度大于左子树高度进行左旋处理

现在我们把第38-41行的注释打开 看一下左旋之后的结果

中序结果是
3	4	5	6	7	8	
左旋处理中
root的左子树高度2
root的右子树高度2

注意

 if(rightHeight()-leftHeight()>1){
            leftRotated();
        }

这里的rightHeight()前没有加this 那么是谁调用的他呢?我们打个断点看一下

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

可以看到此时该函数的调用者对象是this 也就是7这个node节点

换句话说 递归到哪个节点此时正在执行添加方法 就把哪个节点作为根节点去比较它的左右子树的高度

关于右旋以及其他我们之后更新!

发布了39 篇原创文章 · 获赞 19 · 访问量 1464

猜你喜欢

转载自blog.csdn.net/weixin_44222272/article/details/105564691