Java实现AVL树

一、定义AVL树类

/**
 * @Description: AVL树类
 * @Author: Administrator
 * @Version:
 */

public class AVLTree<T extends Comparable<T>> {
    private AVLNode<T> mRoot; //结点

    //AVL树的结点(内部类)
    class  AVLNode<T extends Comparable<T>>{
        T key;  //结点的值
        int height; //高度
        AVLNode<T> left; //左孩子
        AVLNode<T> right; //右孩子

        public AVLNode(T key, AVLNode<T> left, AVLNode<T> right) {
            this.key = key;
            this.left = left;
            this.right = right;
            this.height = 0;
        }
    }
    //构造函数
    public AVLTree() {
        mRoot = null;
    }
    //获取树的高度
    private int  height(AVLNode<T> tree){
        if (tree != null){
            return tree.height;
        }
        return  0;
    }
    public  int getHeight(){
        return height(mRoot);
    }

    //找两个树的最大值
    private int max(int a,int b){
        return a>b ? a : b;
    }
    //前序遍历
    private void preOrder(AVLNode<T> tree){
        if (tree != null){
            System.out.print("["+tree.key+"]   ");
            preOrder(tree.left);
            preOrder(tree.right);
        }
    }
    public void proOrder(){
        preOrder(mRoot);
    }

    //中序遍历
    private void inOrder(AVLNode<T> tree){
        if (tree != null){
            inOrder(tree.left);
            System.out.print("["+tree.key+"]   ");
            inOrder(tree.right);
        }
    }
    public void inOrder(){
        inOrder(mRoot);
    }

    //后序遍历
    private void postOrder(AVLNode<T> tree){
        if (tree != null){
            postOrder(tree.left);
            postOrder(tree.right);
            System.out.print("["+tree.key+"]   ");
        }
    }
    public void postOrder(){
        postOrder(mRoot);
    }

    /*
    * @desc: 查找"AVL树中结点x"的键值为key的结点(递归实现)
    * @param x:结点
    * @param key: 查找的值
    * @return: avl.AVLTree<T>.AVLNode<T>
    */
    private AVLNode<T> search(AVLNode<T> x,T key){
        if (x == null){
            return x;
        }
        int cmp = key.compareTo(x.key); //比较
        if (cmp < 0){ //如果key比x的key小,在x的左子树中找
            return search(x.left,key);
        }else if (cmp > 0){//如果key比x的key大,在x的右子树中找
            return search(x.right,key);
        }else{
            return x;
        }
    }
    public AVLNode<T> search(T key){
        return search(mRoot,key);
    }
    /*
    * @desc: 查找"AVL树中结点x"的键值为key的结点(递归实现)
    * @param x: 结点
    * @param key: 待查找的值
    * @return: avl.AVLTree<T>.AVLNode<T>
    */
    private AVLNode<T> iterativeSearch(AVLNode<T> x, T key){
        while ( x != null){
            int cmp = key.compareTo(x.key);
            if (cmp < 0){
                x = x.left;
            }else if (cmp > 0){
                x = x.right;
            }else{
                return x;
            }
        }
        return x;
    }
    public AVLNode<T> iterativeSearch(T key){
        return iterativeSearch(mRoot,key);
    }

    /*
    * @desc: 查找最小结点:返回tree为根结点的AVL树的最小结点
    * @param tree: AVL树
    * @return: avl.AVLTree<T>.AVLNode<T>
    */
    private AVLNode<T> minNum(AVLNode<T> tree){
        if (tree == null){
            return null;
        }
        while (tree.left != null){ //在tree的左子树中查找
            tree = tree.left;
        }
        return tree;
    }

    public T minNum(){
        AVLNode<T> p = minNum(mRoot);
        if (p != null){
            return p.key;
        }
        return null;
    }

    /*
    * @desc: 查找最大结点:返回tree为根结点的AVL树的最大结点
    * @param tree:
    * @return: avl.AVLTree<T>.AVLNode<T>
    */
    private AVLNode<T> maxNum(AVLNode<T> tree){
        if (tree == null){
            return null;
        }
        while (tree.right != null){ //在tree的右子树中查找
            tree = tree.right;
        }
        return tree;
    }

    public T maxNum(){
        AVLNode<T> p = maxNum(mRoot);
        if (p != null){
            return p.key;
        }
        return null;
    }

    /*
    * @desc: LL,左左对应的情况(左单旋转)
    * @param k2: 结点
    * @return: avl.AVLTree<T>.AVLNode<T>  返回旋转后的根结点
    */
    private AVLNode<T> leftLeftRotate(AVLNode<T> k2){
        AVLNode<T> k1;
        k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;

        k2.height = max(height(k2.left),height(k2.right)) + 1;
        k1.height = max(height(k1.left),k2.height) + 1;

        return k1;
    }
    /*
    * @desc: RR,右右对应的情况(右单旋转)
    * @param k1: 结点
    * @return: avl.AVLTree<T>.AVLNode<T> 旋转后的根结点
    */
    private AVLNode<T> rightRightRotate(AVLNode<T> k1){
        AVLNode<T> k2;
        k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;

        k1.height = max(height(k1.left),height(k1.right)) + 1;
        k2.height = max(height(k2.right),k1.height) + 1;

        return k2;
    }

    /*
    * @desc: LR,左右对应的情况(左双旋转)
    * @param k3: 结点
    * @return: avl.AVLTree<T>.AVLNode<T> 旋转后的根结点
    */
    private AVLNode<T> leftRightRotate(AVLNode<T> k3){
        k3.left = rightRightRotate(k3.left);

        return leftLeftRotate(k3);
    }

    /*
    * @desc: RL,右左对应的情况(右双旋转)
    * @param k1: 结点
    * @return: avl.AVLTree<T>.AVLNode<T> 旋转后的根结点
    */
    private AVLNode<T> rightLeftRotate(AVLNode<T> k1){
        k1.right = leftLeftRotate(k1.right);

        return rightRightRotate(k1);
    }

    /*
    * @desc: 将结点插入到AVL树中,并返回根结点
    * @param tree:AVL树的根结点
    * @param key: 插入的结点的键值
    * @return: avl.AVLTree<T>.AVLNode<T> 返回根结点
    */
    private AVLNode<T> insert(AVLNode<T> tree,T key){
        if (tree == null){ //如果树为空,新建结点
            tree = new AVLNode<T>(key,null,null);
            if (tree == null){
                System.out.println("Error:create avltree node failed!");
                return null;
            }
        }else {
            int cmp = key.compareTo(tree.key);
            if (cmp < 0){ //若key小于根结点,则插入到左子树
                tree.left = insert(tree.left,key);
                //插入结点后,若AVL树失去平衡,则进行相应的调节
                if (height(tree.left) - height(tree.right) == 2){
                    if (key.compareTo(tree.left.key) < 0){
                        tree = leftLeftRotate(tree);
                    }else {
                        tree = leftRightRotate(tree);
                    }
                }
            }else if (cmp > 0){ //若key大于根结点,则插入到右子树
                tree.right = insert(tree.right,key);
                //插入结点后,若AVL树失去平衡,则进行相应的调节
                if (height(tree.right) - height(tree.left) == 2){
                    if (key.compareTo(tree.right.key) > 0){
                        tree = rightRightRotate(tree);
                    }else{
                        tree = rightLeftRotate(tree);
                    }
                }
            }else{ //cmp ==0
                System.out.println("添加失败:不允许添加相同的结点!");
            }
        }
        tree.height = max(height(tree.left),height(tree.right)) + 1;
        return tree;
    }

    public void insert(T key){
        mRoot = insert(mRoot,key);
    }

    /*
    * @desc: 删除结点
    * @param tree:AVL树的根结点
    * @param z: 待删除结点
    * @return: avl.AVLTree<T>.AVLNode<T> 返回根结点
    */
    private AVLNode<T> remove(AVLNode<T> tree,AVLNode<T> z){
        //根为空 或者 没有要删除的结点,直接返回null
        if (tree == null || z == null){
            return null;
        }
        int cmp = z.key.compareTo(tree.key);
        if (cmp < 0){  //待删除结点在tree的左子树中
            tree.left = remove(tree.left,z);

            //删除结点后,若AVL树失去平衡,则进行相应的调节
            if (height(tree.right) - height(tree.left) == 2){
                AVLNode<T> r = tree.right;
                if (height(r.left) > height(r.right)){
                    tree = rightLeftRotate(tree);
                }else{
                    tree = rightRightRotate(tree);
                }
            }
        }else if (cmp > 0){ //待删除结点在tree的右子树中
            tree.right = remove(tree.right,z);
            //删除结点后,若AVL树失去平衡,则进行相应的调节
            if (height(tree.left) - height(tree.right) == 2){
                AVLNode<T> l = tree.left;
                if (height(l.right) > height(l.left)){
                    tree = leftRightRotate(tree);
                }else{
                    tree = leftLeftRotate(tree);
                }
            }
        }else{ //tree是对应要删除的结点
            if ((tree.left != null) &&(tree.right != null)){ //tree的左右孩子都非空
                if (height(tree.left) > height(tree.right)){
                    /*如果tree的左子树比右子树高,则:
                       (1)找出tree的左子树中的最大结点
                       (2)将该最大结点的值赋给tree
                       (3)删除该最大结点
                       这类似于用"tree"的左子树中最大结点做"tree"的替身
                       好处:删除"tree"的左子树中最大结点后,AVL树仍然是平衡的
                     */
                    AVLNode<T> max = minNum(tree.left);
                    tree.key = max.key;
                    tree.left = remove(tree.left,max);
                }else{
                    /*
                       如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高),则
                         (1)找到tree的右子树中的最小结点
                         (2)将该最小结点的值赋给tree
                         (3)删除该最小结点
                        这类似于用"tree"的右子树中最小结点做"tree"的替身;
                        好处:删除"tree的右子树中最小结点"后,AVL树仍然是平衡的
                    */
                    AVLNode<T> min = minNum(tree.right);
                    tree.key = min.key;
                    tree.right = remove(tree.right,min);
                }
            }else{
                AVLNode<T> tmp = tree;
                tree = (tree.left != null)?tree.left : tree.right;
                tmp = null;
            }
        }
        return tree;
    }

    public void remove(T key){
        AVLNode<T> z = search(mRoot,key);
        if (z != null){
            mRoot = remove(mRoot,z);
        }
    }

    /*
    * @desc: 销毁AVL树
    * @param tree: AVL树
    * @return: void
    */
    private void destroy(AVLNode<T> tree){
        if (tree == null){
            return;
        }
        if (tree.left != null){
            destroy(tree.left);
        }
        if (tree.right != null){
            destroy(tree.right);
        }
        tree = null;
    }
    public  void destroy(){
        destroy(mRoot);
    }

    /*
    * @desc: 打印AVL树
    * @param tree:AVL树
    * @param key:结点的键值
    * @param direction:
    *      -- 0 :表示该结点是根结点
    *      -- -1:表示该结点时它的父结点的左孩子
    *      -- 1:表示该结点时它的父结点的右孩子
    * @return: void
    */
    private void print(AVLNode<T> tree,T key,int direction){
        if (tree != null){
            if (direction ==0){ //tree是根结点
                System.out.printf("%2d is root\n",tree.key,key);
            }else{ //tree的分支结点
                System.out.printf("%2d is %2d's %6s child\n",tree.key,key,direction==1?"right":"left");
            }
            print(tree.left,tree.key,-1);
            print(tree.right,tree.key,1);
        }
    }
    public void print(){
        if (mRoot != null){
            print(mRoot,mRoot.key,0);
        }
    }
}

二、测试

/**
 * @Description: AVL树的测试
 * @Author: Administrator
 * @Version:
 */

public class AVLTreeTest {
    private static int arr[]= {33,32,1,4,5,6,17,16,15,14,13,12,11,10,8,9};

    public static void main(String[] args) {
        int i;
        AVLTree<Integer> tree = new AVLTree<>();
        System.out.printf("== 依次添加:");
        for ( i = 0; i < arr.length ; i++) {
            System.out.printf("%d ",arr[i]);
            tree.insert(arr[i]);
        }
        System.out.printf("\n== 前序遍历:");
        tree.proOrder();

        System.out.printf("\n== 中序遍历:");
        tree.inOrder();

        System.out.printf("\n== 后序遍历:");
        tree.postOrder();
        System.out.println();

        System.out.printf("== 高度:%d\n",tree.getHeight());
        System.out.printf("== 最小值:%d\n",tree.minNum());
        System.out.printf("== 最大值:%d\n",tree.maxNum());

        System.out.println("== 树的详细信息:");
        tree.print();

        i = 8;
        System.out.printf("\n== 删除结点:%d",i);
        tree.remove(i);

        System.out.printf("\n== 高度:%d",tree.getHeight());
        System.out.printf("\n== 中序遍历:");
        tree.inOrder();
        System.out.printf("\n== 树的详细信息:\n");
        tree.print();

        tree.destroy();//销毁二叉树
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上庸者-不服周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值