AVL树的功能实现

平衡二叉树(AVL)

二叉树是一种非常适合查找的数据结构,因而引入AVL树,BST树,红黑树
一、性质:
(1)它是一棵空树或者它的左右子树高度差不能超过1.且它的左右两个子树也是二叉平衡树。
(2)它是一种BST树,因而它拥有BST树的性质
二、目的:
用于增,删,查
造成AVL树不平衡有四种情况,解决策略如下:
(1)右孩子的右孩子造成:

child =node.right
node.right=child.left;
child.left=node;
(2)右孩子的左孩子造成:
进行两次旋转

在这里插入图片描述
(3)由左孩子的左孩子引起失衡(左平衡)

在这里插入图片描述

(4)由左孩子的右孩子引起的不平衡
发生两次旋转即可
在这里插入图片描述
下边是我们用递归实现的接口:
先创建节点

class AVLNode <T extends Comparable<T>> {
    private T data;
    private AVLNode<T>Left;
    private AVLNode<T>Right;
    private int hight;//记录当前节点的高度值

    public AVLNode() {
    }

    public AVLNode(T data, AVLNode<T> left, AVLNode<T> right, int hight) {
        this.data = data;
        Left = left;
        Right = right;
        this.hight = hight;
    }

    public T getData() {
        return data;
    }

    public AVLNode<T> getLeft() {
        return Left;
    }

    public AVLNode<T> getRight() {
        return Right;
    }

    public void setData(T data) {
        this.data = data;
    }

    public void setLeft(AVLNode<T> left) {
        Left = left;
    }

    public void setRight(AVLNode<T> right) {
        Right = right;
    }

    public int getHight() {
        return hight;
    }

    public void setHight(int hight) {
        this.hight = hight;
    }
}

创建一颗AVL树:

class AVLTree<T extends Comparable<T>>{
      private AVLNode<T>root;

    public AVLTree() {
        this.root = null;
    }
    public void insert(T data){
       this. root=insert(this.root,data );
    }

四种旋转操作:
以参数node为根节点进行左旋操作,把旋转后的树的根节点返回

/**
     * 以参数node为根节点进行左旋操作,把旋转后的树的根节点返回
     * @param
     * @return
     */
  public   AVLNode<T> leftRotate(AVLNode<T> node){
         AVLNode<T> child=node.getRight();
         node.setRight(child.getLeft());
         child.setLeft(node);
        //旋转之后更新高度
      node.setHight(maxHeigh(node.getLeft(), node.getRight())+1);
       child.setHight(maxHeigh(child.getLeft(), child.getRight())+1);
       return child;
     }
在这里插入代码片

右旋

/**
     * 以参数node为根节点进行右旋操作,把旋转后的树的根节点返回
     * @param
     * @return
     */
     public AVLNode<T> rightRotate(AVLNode<T> node){
      AVLNode<T> child=node.getLeft();
      node.setLeft(child.getRight());
      child.setRight(node);
      //更新child node 的高度
         node.setHight(maxHeigh(node.getLeft(), node.getRight())+1);
         child.setHight(maxHeigh(child.getLeft(), child.getRight())+1);
            return child;
     }

左平衡操作

/**
     * 以参数node为根节点进行左平衡操作,把旋转后的树的根节点返回
     * @param node
     * @return
     */
    public AVLNode<T>leftBalance(AVLNode<T> node){
       node.setLeft( leftRotate( node.getLeft()));
        return rightRotate(node);
    }

右平衡操作

/**
     * 以参数node为根节点进行右平衡操作,把旋转后的树的根节点返回
     * @param node
     * @return
     */
    public AVLNode<T> rightBanlance(AVLNode<T>node){
        //以node.right做右旋操作
        AVLNode<T>child=node.getRight();
        node.setRight(rightRotate(child));
       return leftRotate(node);
    }

插入操作(递归方式)

public AVLTree() {
        this.root = null;
    }
    public void insert(T data){
       this. root=insert(this.root,data );
    }
    //插入
    private   AVLNode<T> insert( AVLNode<T> root,T data) {
        if (root == null) {
            return new AVLNode<>(data, null, null, 1);
        }
        if (root.getData().compareTo(data) > 0) {
            root.setLeft(insert(root.getLeft(), data));
            //插入过程会发生左右不平衡的情况
            if (height(root.getLeft()) - height(root.getRight()) > 1) {
                //判断子树的那个分支引起
                if (height(root.getLeft().getLeft()) >=height(root.getLeft().getRight()) ) {
                    //右旋转
                    root = rightRotate(root);
                } else {
                    //左平衡
                    root = leftBalance(root);
                }
            }
        } else if (root.getData().compareTo(data) < 0) {
            root.setRight(insert(root.getRight(), data));
            if (height(root.getRight()) - height(root.getLeft())> 1) {
                if (height(root.getRight().getRight()) >= height(root.getRight().getLeft())) {
                    root = leftRotate(root);
                } else {
                    root = rightBanlance(root);
                }
            }
        }
        //更新节点高度
        root.setHight(maxHeigh(root.getLeft(), root.getRight()) + 1);
        return root;
    }
    

删除(递归方式)

 /**
     * 实现AVL树的递归删除
     * @param data
     */
 public  void remove(T data){
      this.root= remove(this.root, data);
    }
    private AVLNode<T> remove(AVLNode<T> root,T data) {
        if (root == null) {
            return null;
        }
        if (root.getData().compareTo(data) > 0) {
            root.setLeft(remove(root.getLeft(), data));
            //删除之后,可能会引起不平衡,进行旋转并且更新高度
            if (height(root.getLeft()) - height(root.getRight()) > 1) {
                if(height(root.getRight().getRight())>height(root.getRight().getLeft())){
                    root=leftRotate(root);
                }else {
                    root=rightBanlance(root);
                }

            }
        } else if (root.getData().compareTo(data) < 0) {
            root.setRight(remove(root.getRight(), data));
            if (height(root.getLeft().getLeft()) >= height(root.getLeft().getRight())) {
                root = rightRotate(root);
            } else {
                root = leftBalance(root);
            }
        }
         else {
            if (root.getLeft() != null && root.getLeft() != null) {
                //要根据待删节点的左右子树的高度,左子树过高则找前驱,右子树过高则找后继
                if (height(root.getLeft())>height(root.getRight())) {
                    //找前驱
                    AVLNode<T> pre = root.getLeft();
                    while (pre.getRight() != null) {
                        pre = pre.getRight();
                    }
                    root.setData(pre.getData());
                    root.setLeft(remove(root.getLeft(), pre.getData()));
                }else {
                    //找后继
                    AVLNode<T>post=root.getRight();
                    while(post.getLeft()!=null){
                        post=post.getLeft();
                    }root.setData(post.getData());
                    root.setRight(remove(root.getRight(), post.getData()));
                }
            }else {
                //含一个节点和叶子节点
                // AVLNode<T> child=root.getLeft();
                if (root.getLeft() != null) {
                    return root.getLeft();
                } else if (root.getRight() != null) {
                    return root.getRight();
                } else {
                    return null;
                }
            }
        }
        return root;
    }

分别以前序遍历,中序遍历,后序遍历方式打印出元素顺序
(前序遍历)

//前序遍历
    public void preSOrder(){
    preOrder(this.root);
    }
    public void preOrder(AVLNode<T>root){
    if(root==null){
        return ;
    }
    System.out.println(root);
    preOrder(root.getLeft());
    preOrder(root.getRight());
    }

(中序遍历)

 //中序遍历
    public void inOrder(){
      inOder(this.root);
    }
    public void inOder(AVLNode<T> root){
    if(root==null){
        return;
    }
    inOder(root.getLeft());
    System.out.println(root.getData());
    inOder(root.getRight());
    }

(后序遍历)

//后序遍历
    public void postOrder(){
   postOrder(this.root);
    }
    public void postOrder(AVLNode<T> root){
    if(root==null){
        return;
    }
  postOrder(root.getLeft());
  postOrder(root.getRight());
    System.out.println(root.getData());
    }

节点个数

//计算BST树的节点个数
    public int num_Data(){
   return num_Data(this.root);
}
public int num_Data(AVLNode<T> root){
    if(root==null){
        return 0;
    }
    return num_Data(root.getLeft())+num_Data(root.getRight())+1;
}

测试用例

public class TestDome {
    public static void main(String[] args) {
        AVLTree<Integer> avl = new AVLTree<>();
        int[] arr = {1, 2, 3,4,5,6,7,8,9,10};
        for (int i : arr) {
            avl.insert(i);
        }
        //avl.remove(2);

       // avl.num_Data();
    int n=avl.num_Data();
        System.out.println();
//        System.out.println("================");
//        avl.inOrder();
//        System.out.println("================");
//        avl.postOrder();
      //  System.out.println( avl.quire(2));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值