AVL树的实现

/**
 * @author LOHAS
 * @time 2019-10-4
 * @subject ADT AVLTree
 * @Main-method:
 * 1) Tree Constructor
 * 2) Get node's height
 * 3) Traverse
 * 4) findMax
 * 5) findMin
 * 6) rotateLLTree
 * 7) rotateLRTree
 * 8) rotateRLTree
 * 9) roatteRRTree
 * 10) insert
 * 11) remove
 * 12) destroy
 */

package tree;

import org.junit.Test;

public class MyAVLTree<T extends Comparable<T>> {
    //定义根节点
    public AVLNode mroot;

    //构造内部类,实现结点的构造函数
    class AVLNode<T> {
        private T key;  //结点的值
        private AVLNode left;  //左孩子
        private AVLNode right;  //右孩子
        private int height;  //结点的高度

        public AVLNode(T key) {
            this(key, null, null);
        }

        public AVLNode(T key, AVLNode<T> left, AVLNode<T> right) {
            this.key = key;
            this.left = left;
            this.right = right;
            this.height = 0;
        }
    }

    //构造函数
    public MyAVLTree2() {
        mroot = null;
    }

    /**
     * 获取子树的高度
     *
     * @param tree
     * @return 返回子树高度值
     */
    public int height(AVLNode<T> tree) {
        if (tree == null)
            return 0;
        return tree.height;
    }

    /**
     * 获取树的高度
     *
     * @return
     */
    public int height() {
        return height(mroot);
    }

    /**
     * 先序遍历
     *
     * @param node
     */
    private void preOrder(AVLNode<T> node) {
        if (node != null) {
            System.out.print(node.key + "\t");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    public void preOrder() {
        preOrder(mroot);
    }

    /**
     * 中序遍历
     *
     * @param node
     */
    private void inOrder(AVLNode<T> node) {
        if (node != null) {
            inOrder(node.left);
            System.out.print(node.key + "\t");
            inOrder(node.right);
        }
    }

    public void inOrder() {
        inOrder(mroot);
    }

    /**
     * 后序遍历
     *
     * @param node
     */
    private void postOrder(AVLNode<T> node) {
        if (node != null) {
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.key + "\t");
        }
    }

    public void postOrder() {
        postOrder(mroot);
    }

    /**
     * 【递归实现】获取AVLTree中最小的结点
     *
     * @param node
     * @return
     */
    private AVLNode<T> findMin(AVLNode<T> node) {
        if (node == null)
            return null;
        if (node.left == null)
            return node;
        return node.left;
    }

    public AVLNode<T> findMin() {
        return findMin(mroot);
    }

    /**
     * 获取AVLTree中最大的结点
     *
     * @param node
     * @return
     */
    private AVLNode<T> findMax(AVLNode<T> node) {
        if (node == null)
            return null;
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }

    public AVLNode<T> findMax() {
        return findMin(mroot);
    }

    /**
     * 旋转LL类型的子树(右旋)
     *
     * @param k2 被破坏平衡树的根结点
     * @return 返回平衡后得树
     */
    private AVLNode<T> rotateLLTree(AVLNode<T> k2) {
        AVLNode<T> k1;
        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), k2.height) + 1;

        return k1;
    }

    /**
     * 旋转RR类型的子树(左旋)
     *
     * @param k2 被破坏平衡后的子树的根结点
     * @return 平衡后的子树(根结点)
     */
    private AVLNode<T> rotateRRTree(AVLNode<T> k2) {
        AVLNode<T> k1;
        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.right), k2.height) + 1;

        return k1;
    }

    /**
     * 旋转LR类型的子树
     *
     * @param k3
     * @return
     */
    private AVLNode<T> rotateLRTree(AVLNode<T> k3) {
        //先进行RR类型的旋转(左旋)
        k3.left = rotateRRTree(k3.left);
        //再进行LL类型的旋转(右旋)
        return rotateLLTree(k3);
    }

    /**
     * 旋转RL类型的子树
     *
     * @param k3
     * @return
     */
    private AVLNode<T> rotateRLTree(AVLNode<T> k3) {
        //先进行LL类型的旋转(右旋)
        k3.right = rotateLLTree(k3.right);
        //再进行RR类型的旋转(左旋)
        return rotateRRTree(k3);
    }

    /**
     * 插入结点
     *
     * @param node
     * @param key
     * @return
     */
    private AVLNode<T> insert(AVLNode<T> node, T key) {
        if (node == null) {

            node = new AVLNode<T>(key);
        } else {
            if (key.compareTo(node.key) < 0) {
                node.left = insert(node.left, key);
                //判断插入结点后是否平衡,若不平衡则需调整
                if (height(node.left) - height(node.right) == 2) {  //在左子树中插入的
                    if (key.compareTo((T) node.left.key) < 0)  //判断是LL还是LR
                        node = rotateLLTree(node);
                    else
                        node = rotateLRTree(node);
                }
            } else if (key.compareTo(node.key) > 0) {
                node.right = insert(node.right, key);
                //判断插入结点后是否平衡,若不平衡则需调整
                if (height(node.right) - height(node.left) == 2) {  //在右子树中插入的
                    if (key.compareTo((T) node.right.key) > 0)  //判断是RR还是RL
                        node = rotateRRTree(node);
                    else
                        node = rotateRLTree(node);
                }
            } else {
                System.out.println("插入错误:已有相同结点!");
            }
        }

        //计算结点的高度
        node.height = Math.max(height(node.left), height(node.right)) + 1;

        return node;
    }

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

    /**
     * 删除节点
     *
     * @param root 根节点
     * @param node 被删除的节点
     * @return
     */
    private AVLNode<T> remove(AVLNode<T> root, AVLNode<T> node) {
        if (root == null || node == null) {
            return null;
        }
        int value = node.key.compareTo(root.key);
        if (value < 0) {
            root.left = remove(root.left, node);

            //删除左子树的节点后,右子树可能会比左子树高
            if (height(root.right) - height(root.left) == 2) {
                AVLNode<T> r = root.right;
                //判断是RR还是RL类型
                if (height(r.left) < height(r.right)) {  //RR类型
                    root = rotateRRTree(root);
                } else   //RL类型
                    root = rotateRLTree(root);
            }
        } else if (value > 0) {
            root.right = remove(root.right, node);

            //删除右子树的节点后,左子树可能会比右子树高
            if (height(root.left) - height(root.right) == 2) {
                AVLNode<T> l = root.left;
                if (height(l.left) > height(l.right)) {  //LL类型
                    root = rotateLLTree(root);
                } else {  //LR类型
                    root = rotateLRTree(root);
                }
            }
        } else {  //找到要删除的结点
            //被删除的结点左右子树都不为空的情况
            if (root.left != null && root.right != null) {
                //若是结点的左子树比右子树高
                //则从左子树中选出最大值来替换要被删除的结点
                // 把用来替换的结点删除
                //这样做的好处是删除节点之后树仍然是平衡的
                if (height(root.left) > height(root.right)) {
                    AVLNode<T> leftMax = findMax(root.left);
                    root.key = leftMax.key;
                    root.left = remove(root.left, leftMax);
                } else {
                    //若是右子树比左子树高或相等
                    //从右子树选出最小的结点来替换要删除的结点
                    //删除用来替换的结点
                    //好处是若右子树比左子树高则删除节点之后树仍然是平衡的
                    AVLNode<T> rightMin = findMin(root.right);
                    root.key = rightMin.key;
                    root.right = remove(root.right, rightMin);
                }
            } else {  //被删除结点左右子树非都不为空的情况
                root = (root.left == null) ? root.right : root.left;
            }
        }
        return root;
    }

    public void remove(T key) {
        AVLNode<T> node = new AVLNode<>(key);
        remove(mroot, node);
    }

    /**
     * 销毁AVLTree
     *
     * @param node
     */
    private void destroy(AVLNode<T> node) {
        if (node == null)
            return;
        if (node.left != null)
            destroy(node.left);
        if (node.right != null)
            destroy(node.right);
        node = null; //根节点的处理
    }

    public void destroy() {
        destroy(mroot);
    }

    /*
     * 打印"二叉查找树"
     *
     * key        -- 节点的键值
     * direction  --  0,表示该节点是根节点;
     *               -1,表示该节点是它的父结点的左孩子;
     *                1,表示该节点是它的父结点的右孩子。
     */
    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 and its height is %2d\n", tree.key, key, direction == 1 ? "right" : "left", tree.height);

            print(tree.left, tree.key, -1);
            print(tree.right, tree.key, 1);
        }
    }

    public void print() {
        if (mroot != null)
            print(mroot, (T) mroot.key, 0);
    }

	//测试代码
    @Test
    public void MyAVLTreeTest() {
        MyAVLTree2<Integer> tree = new MyAVLTree2<Integer>();
        int arr[] = {3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9};
        System.out.println("==依次添加==");
        for (int i : arr) {
            System.out.print(i + "\t");
            tree.insert(i);
        }
        //tree.remove(2);
        System.out.println("\n先序遍历");
        tree.inOrder();
        System.out.println();
        tree.print();
        System.out.println(tree.height());
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值