JAVA实现 红黑树与 二叉平衡树(AVL)

JAVA实现 红黑树与 二叉平衡树(AVL)

平衡二叉树(AVL)

平衡二叉查找树:简称平衡二叉树。由前苏联的数学家Adelse-Velskil和Landis在1962年提出的高度平衡的二叉树,根据科学家的英文名也称为AVL树。它具有如下几个性质:

  • 可以是空树。
  • 假如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过1
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author LiaoJL
 * @description TODO 二叉平衡树简单实现
 * @file AvlTree.java
 * @email jinlongliao@foxmail.com
 * @date 2020/4/21 12:45
 */
public class AvlTree<T extends Comparable<? super T>> {
    private static class AvlNode<T> {
        //avl树节点
        AvlNode(T theElement) {
            this(theElement, null, null);
        }

        AvlNode(T theElement, AvlNode<T> lt, AvlNode<T> rt) {
            element = theElement;
            left = lt;
            right = rt;
            height = 0;
        }

        // 节点中的数据
        T element;
        // 左儿子
        AvlNode<T> left;
        // 右儿子
        AvlNode<T> right;
        // 节点的高度
        int height;
    }

    //avl树根
    private AvlNode<T> root;

    public AvlTree() {
        root = null;
    }

    public AvlNode<T> getRoot() {
        return root;
    }

    //在avl树中插入数据,重复数据复略
    public void insert(T x) {
        root = insert(x, root);
    }

    //在avl中删除数据,这里并未实现
    public void remove(T x) {
        System.out.println("Sorry, remove unimplemented");
    }

    //在avl树中找最小的数据
    public T findMin() {
        if (isEmpty())
            System.out.println("树空");
        ;
        return findMin(root).element;
    }

    //在avl树中找最大的数据
    public T findMax() {
        if (isEmpty())
            System.out.println("树空");
        return findMax(root).element;
    }

    //搜索
    public boolean contains(T x) {
        return contains(x, root);
    }

    public void makeEmpty() {
        root = null;
    }

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

    /**
     * 排序输出avl树
     */
    public void printTree() {
        if (isEmpty()) {
            log.info("Empty tree");
        } else {
            printTree(root);
        }
    }

    /**
     * @param node 要插入的节点
     * @param root 树根节点
     * @return
     */
    private AvlNode<T> insert(T node, AvlNode<T> root) {
        if (root == null) {
            return new AvlNode<T>(node, null, null);
        }

        int compareResult = node.compareTo(root.element);

        int heightRight = height(root.right);
        int heightLeft = height(root.left);
        if (compareResult < 0) {
            //将x插入左子树中,使用递归思想
            root.left = insert(node, root.left);
            //打破平衡
            if (heightLeft - heightRight > 1)
                if (node.compareTo(root.left.element) < 0) {
                    /**
                     *LL型(左左型)
                     */
                    root = rotateWithLeftChild(root);
                } else {
                    /**
                     * LR型(左右型)
                     */
                    root = doubleWithLeftChild(root);
                }
        } else if (compareResult > 0) {
            root.right = insert(node, root.right);//将x插入右子树中
            if (heightRight - heightLeft == 2)
            /**
             * 打破平衡
             */
                if (node.compareTo(root.right.element) > 0) {
                    //RR型(右右型)
                    root = rotateWithRightChild(root);
                } else {                    //RL型
                    root = doubleWithRightChild(root);
                }
        } else
            ;  // 重复数据,什么也不做
        /**
         * 更新树操作
         */
        root.height = Math.max(heightLeft, heightRight) + 1;
        return root;
    }

    //找最小
    private AvlNode<T> findMin(AvlNode<T> t) {
        if (t == null)
            return t;
        while (t.left != null)
            t = t.left;
        return t;
    }

    //找最大
    private AvlNode<T> findMax(AvlNode<T> t) {
        if (t == null)
            return t;
        while (t.right != null)
            t = t.right;
        return t;
    }

    //搜索(查找)
    private boolean contains(T x, AvlNode t) {
        while (t != null) {
            int compareResult = x.compareTo((T) t.element);

            if (compareResult < 0)
                t = t.left;
            else if (compareResult > 0)
                t = t.right;
            else
                return true;    // Match
        }
        return false;   // No match
    }

    /**
     * 中序遍历avl树
     */

    private void printTree(AvlNode<T> t) {
        if (t != null) {
            printTree(t.left);
            log.info("node: {},height:{}", t.element, t.height);
            printTree(t.right);
        }
    }

    /**
     * 求高度
     *
     * @param node
     * @return
     */
    public int height(AvlNode<T> node) {
        return node == null ? -1 : node.height;
    }

    //带左子树旋转,适用于LL型
    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), k2.height) + 1;
        return k1;
    }

    //带右子树旋转,适用于RR型
    private AvlNode<T> rotateWithRightChild(AvlNode<T> k1) {
        AvlNode<T> k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;
        k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
        k2.height = Math.max(height(k2.right), k1.height) + 1;
        return k2;
    }

    //双旋转,适用于LR型
    private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

    //双旋转,适用于RL型
    private AvlNode<T> doubleWithRightChild(AvlNode<T> k1) {
        k1.right = rotateWithLeftChild(k1.right);
        return rotateWithRightChild(k1);
    }

    private static final Logger log = LoggerFactory.getLogger(AvlTree.class);

}

红黑树(BR)

  • 节点是红色或黑色。
  • 根节点是黑色。
  • 所有叶子都是黑色。(叶子是NUIL节点)
  • 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author LiaoJL
 * @description TODO 二叉平衡树简单实现
 * @file AvlTree.java
 * @email jinlongliao@foxmail.com
 * @date 2020/4/21 12:45
 */
public class AvlTree<T extends Comparable<? super T>> {
    private static class AvlNode<T> {
        //avl树节点
        AvlNode(T theElement) {
            this(theElement, null, null);
        }

        AvlNode(T theElement, AvlNode<T> lt, AvlNode<T> rt) {
            element = theElement;
            left = lt;
            right = rt;
            height = 0;
        }

        // 节点中的数据
        T element;
        // 左儿子
        AvlNode<T> left;
        // 右儿子
        AvlNode<T> right;
        // 节点的高度
        int height;
    }

    //avl树根
    private AvlNode<T> root;

    public AvlTree() {
        root = null;
    }

    public AvlNode<T> getRoot() {
        return root;
    }

    //在avl树中插入数据,重复数据复略
    public void insert(T x) {
        root = insert(x, root);
    }

    //在avl中删除数据,这里并未实现
    public void remove(T x) {
        System.out.println("Sorry, remove unimplemented");
    }

    //在avl树中找最小的数据
    public T findMin() {
        if (isEmpty())
            System.out.println("树空");
        ;
        return findMin(root).element;
    }

    //在avl树中找最大的数据
    public T findMax() {
        if (isEmpty())
            System.out.println("树空");
        return findMax(root).element;
    }

    //搜索
    public boolean contains(T x) {
        return contains(x, root);
    }

    public void makeEmpty() {
        root = null;
    }

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

    /**
     * 排序输出avl树
     */
    public void printTree() {
        if (isEmpty()) {
            log.info("Empty tree");
        } else {
            printTree(root);
        }
    }

    /**
     * @param node 要插入的节点
     * @param root 树根节点
     * @return
     */
    private AvlNode<T> insert(T node, AvlNode<T> root) {
        if (root == null) {
            return new AvlNode<T>(node, null, null);
        }

        int compareResult = node.compareTo(root.element);

        int heightRight = height(root.right);
        int heightLeft = height(root.left);
        if (compareResult < 0) {
            //将x插入左子树中,使用递归思想
            root.left = insert(node, root.left);
            //打破平衡
            if (heightLeft - heightRight > 1)
                if (node.compareTo(root.left.element) < 0) {
                    /**
                     *LL型(左左型)
                     */
                    root = rotateWithLeftChild(root);
                } else {
                    /**
                     * LR型(左右型)
                     */
                    root = doubleWithLeftChild(root);
                }
        } else if (compareResult > 0) {
            root.right = insert(node, root.right);//将x插入右子树中
            if (heightRight - heightLeft == 2)
            /**
             * 打破平衡
             */
                if (node.compareTo(root.right.element) > 0) {
                    //RR型(右右型)
                    root = rotateWithRightChild(root);
                } else {                    //RL型
                    root = doubleWithRightChild(root);
                }
        } else
            ;  // 重复数据,什么也不做
        /**
         * 更新树操作
         */
        root.height = Math.max(heightLeft, heightRight) + 1;
        return root;
    }

    //找最小
    private AvlNode<T> findMin(AvlNode<T> t) {
        if (t == null)
            return t;
        while (t.left != null)
            t = t.left;
        return t;
    }

    //找最大
    private AvlNode<T> findMax(AvlNode<T> t) {
        if (t == null)
            return t;
        while (t.right != null)
            t = t.right;
        return t;
    }

    //搜索(查找)
    private boolean contains(T x, AvlNode t) {
        while (t != null) {
            int compareResult = x.compareTo((T) t.element);

            if (compareResult < 0)
                t = t.left;
            else if (compareResult > 0)
                t = t.right;
            else
                return true;    // Match
        }
        return false;   // No match
    }

    /**
     * 中序遍历avl树
     */

    private void printTree(AvlNode<T> t) {
        if (t != null) {
            printTree(t.left);
            log.info("node: {},height:{}", t.element, t.height);
            printTree(t.right);
        }
    }

    /**
     * 求高度
     *
     * @param node
     * @return
     */
    public int height(AvlNode<T> node) {
        return node == null ? -1 : node.height;
    }

    //带左子树旋转,适用于LL型
    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), k2.height) + 1;
        return k1;
    }

    //带右子树旋转,适用于RR型
    private AvlNode<T> rotateWithRightChild(AvlNode<T> k1) {
        AvlNode<T> k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;
        k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
        k2.height = Math.max(height(k2.right), k1.height) + 1;
        return k2;
    }

    //双旋转,适用于LR型
    private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

    //双旋转,适用于RL型
    private AvlNode<T> doubleWithRightChild(AvlNode<T> k1) {
        k1.right = rotateWithLeftChild(k1.right);
        return rotateWithRightChild(k1);
    }

    private static final Logger log = LoggerFactory.getLogger(AvlTree.class);

}

测试代码

import com.google.gson.Gson;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author LiaoJL
 * @description TODO
 * @file TreeTest.java
 * @email jinlongliao@foxmail.com
 * @date 2020/4/21 11:18
 */
public class TreeTest {
    private static final Logger log = LoggerFactory.getLogger(TreeTest.class);

    @Test
    public void testAvlTree() {
        AvlTree<Integer> t = new AvlTree<>();
        final int NUMS = 200;
        final int GAP = 17;
        log.info("Checking... (no more output means success)");
        for (int i = GAP; i != 0; i = (i + GAP) % NUMS) {
            t.insert(i);
        }
        t.printTree();
        log.info(new Gson().toJson(t));
    }

    @Test
    public void testRbTree() {
        DRBTree<Integer> tree = new DRBTree<>();
        int[] a = {10, 20, 30, 40, 50, 60, 70, 80, 90};
//红黑树添加测试
        for (int i = 0; i < a.length; i++) {
            tree.insert(a[i]);
        }

        DRBTree.RBNode<Integer> src = tree.getRoot();
        log.info(new Gson().toJson(src));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值