AVL树的插入与删除---Java实现

AVL树的定义:带有平衡条件的二叉查找树,其左右子树的高度差小于等于1。通过对树的旋转保持平衡。
本文是通过保存高度值实现删除和插入

准备工作
public class AvlTree<T extends Comparable<? super T>> {
    //保存根节点
    private AvlNode<T> root;
    //定义节点
    private static class AvlNode<T>{
        AvlNode<T> left;//左儿子
        AvlNode<T> right;//右儿子
        T data;//数据域
        int height;//高度
        public AvlNode(T data){
            this(data,null,null);
        }
        public AvlNode(T d,AvlNode<T> l,AvlNode<T> r){
            left=l;
            right=r;
            data=d;
            height=0;
        }
    }

    public AvlTree(){
        clear();
    }

    private int height(AvlNode<T> t){
        return t==null?-1:t.height;
    }

    public boolean isEmpty(){
        return root==null;
    }

    public void insert(T data){
        root=insert(root,data);
    }

    public int getHeight(){
        return height(root);
    }

    public void clear(){
        root=null;
    }

    public void remove(T data){
        root=remove(root,data);
    }

    public T findMin(){
        return findMin(root).data;
    }

    public void printTree(){
        printTree(root);
    }

    private void printTree(AvlNode<T> t){
        if(t==null)
            return;
        printTree(t.left);
        System.out.println(t.data);
        printTree(t.right);
    }

    private AvlNode<T> findMin(AvlNode<T> t){
        if(isEmpty()){
            return null;
        }
        if(t.left==null)
            return t;
        else
            return findMin(t.left);
    }

    //右双旋转
    private AvlNode<T> doubleWithRightChild(AvlNode<T> k3) {
        k3.right=rotateWithLeftChild(k3.right);
        return rotateWithRightChild(k3);
    }

    //右单旋转
    private AvlNode<T> rotateWithRightChild(AvlNode<T> k2) {
        AvlNode<T> k1 = k2.right;
        k2.right=k1.left;
        k1.left=k2;
        k2.height=Math.max(height(k2.left), height(k2.right))+1;
        k1.height=Math.max(height(k1.left), height(k1.right))+1;
        return k1;
    }

    //双旋转其实就是两次的单旋转
    private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
        k3.left=rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

    //左单旋转
    private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2) {
        AvlNode<T> k1 = k2.left;
        k2.left=k1.right;
        k1.right=k2;
        k2.height=Math.max(height(k2.left), height(k2.right))+1;
        k1.height=Math.max(height(k1.left), height(k1.right))+1;
        return k1;
    }
  1. 插入
private AvlNode<T> insert(AvlNode<T> t, T data) {
        if(t==null){
            return new AvlNode<T>(data);
        }
        int comparaResult =data.compareTo(t.data);
        if(comparaResult<0){
            t.left=insert(t.left,data);
            if(height(t.left)-height(t.right)==2){//不平衡条件
                if(data.compareTo(t.left.data)<0){
                    t=rotateWithLeftChild(t);
                }else{
                    t=doubleWithLeftChild(t);
                }
            }
        }
        else if(comparaResult>0){
            t.right=insert(t.right,data);
            if(height(t.right)-height(t.left)==2){
                if(data.compareTo(t.right.data)>0){
                    t=rotateWithRightChild(t);
                }else{
                    t=doubleWithRightChild(t);
                }
            }
            }
        else
            ;//重复的值,直接返回。
        t.height=Math.max(height(t.left), height(t.right))+1;
        return t;
    }

2.删除:如果删除并不是非常频繁,采用惰性删除是最好的方式。本文没有采用这样的策略。

private AvlNode<T> remove(AvlNode<T> t,T data){
        if(t==null)
            return t;//没有找到
        int compareResult = data.compareTo(t.data);
        if(compareResult<0){//往左走
            t.left=remove(t.left,data);

            //在左子树中删除后该节点失衡,若失衡,则可以肯定的是该节点的右子树比左子树高
            if (height(t.right) - height(t.left) == 2) {
                //一字型失衡,单旋转
                if (height(t.right.right)>=height(t.right.left)) {
                    t = rotateWithRightChild(t);
                } else {//之字形失衡,双旋转
                    t = doubleWithRightChild(t);
                }

            }
        }else if(compareResult>0){//往右走
            t.right=remove(t.right,data);
            if (height(t.left) - height(t.right) == 2  ) {
                if(t.left!=null){
                if (height(t.left.left)>=height(t.left.right)) {
                    t = rotateWithLeftChild(t);
                } else {
                    t = doubleWithLeftChild(t);
                }
                }
            }
        //找到了要删除的节点,该节点左右子树都不为空
        }else if(t.left!=null&&t.right!=null){
        //特殊情况,当右子树的最小节点就是右儿子并且右儿子的右子树为空
            boolean iooo=(t.right==findMin(t.right)&&t.right.right==null);//判定结果
            t.data=findMin(t.right).data;//用右子树的最小节点替换该节点
            t.right=remove(t.right,t.data);//删除右子树的最小节点
            if(iooo){//特殊情况成立,则节点已经失衡,左单旋转
                t=rotateWithLeftChild(t);
            }
        }else{//找到了要删除的节点,该节点不是满节点
            t=t.left!=null?t.left:t.right;
        }
        if (t != null) {//更新高度
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        }
        return t;
    }
    原文作者:AVL树
    原文地址: https://blog.csdn.net/u013030203/article/details/46913231
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞