java算法- AVL树

当前节点的左子树高度减去右子树高度,高度在-1到1之间。

平衡二叉树(又称AVL树)

和AVL树的比较
AVL树是一棵严格的平衡树,它所有的子树都满足二叉平衡树的定义。因此AVL树高被严格控制在XXX,因此AVL树的查找比较高效。但AVL树插入、删除结点后旋转的次数比红黑树多。

红黑树用非严格的平衡来降低插入删除时旋转的次数。

因此,如果你的业务中查找远远多于插入、删除,那选AVL树; 
如果查找、插入、删除频率差不多,那么选择红黑树。

package com.numberone.tree;

import java.util.LinkedList;

/**
 *            7
 *      4          9
 *   3     5   8      10
 * element 需要自己实现Comparable
 * @param <T>
 */
public class AVLBalanceTree<T extends Comparable<T>> {

    private TreeNode<T> root;

    public AVLBalanceTree() {
    }

    private class TreeNode<E> {
        T element;
        int height;
        TreeNode<T> left;
        TreeNode<T> right;

        TreeNode(T e) {
            element = e;
        }

        boolean isBalanced() {
            int leftHeight = left == null ? -1 : left.height;
            int rightHeight = right == null ? -1 : right.height;
            return Math.abs(leftHeight - rightHeight) <= 1 ? true : false;
        }

        public String toString() {
            return "Element:" + element + " Height:" + height + " Balanced:" + isBalanced();
        }
    }

    /**
     * 插入节点
     * 非递归算法部分
     * @param e
     */
    public void insertNonRecursive(T e) {
        LinkedList<TreeNode<T>> trace = new LinkedList<>();
        insertNonRecursive0(e, trace);
        reBalanceAfterInsert(trace, e);
    }

    /**
     * 删除节点
     * @param e
     */
    public void removeNonRecursive(T e) {
        LinkedList<TreeNode<T>> trace = new LinkedList<>();
        TreeNode<T> current = root;
        trace.push(current);
        // 尝试删除,该节点没有儿子或者只有一个儿子
        if (tryRemove(e, trace, current)) {
            // 更新节点高度信息,修正平衡状态
            // 此时栈顶为被删除节点的父节点或者空栈
            if (trace.isEmpty()) {
                return;
            }
            // 弹出栈,更新高度信息并检查平衡
            reBalanceAfterRemove(trace, e);
        } else {
            // 尝试失败,该节点有两个儿子,此时栈顶元素即为将要删除的节点A
            current = trace.peek();
            // 找到A的右子树中最小的节点B,该节点没有左儿子
            TreeNode<T> rMin = findMin(current.right);
            // 此时删除目标变为最小的右儿子B
            tryRemove(rMin.element, trace, current);
            reBalanceAfterRemove(trace, rMin.element);
            // 删除完成,将B的值替换到原来要删除的节点A上
            current.element = rMin.element;
        }
    }

    private int calHeight(TreeNode<T> node) {
        if (node == null) {
            return -1;
        }
        int leftHeight = node.left == null ? -1 : node.left.height;
        int rightHeight = node.right == null ? -1 : node.right.height;
        return Math.max(leftHeight, rightHeight) + 1;
    }

    private void reBalanceAfterInsert(LinkedList<TreeNode<T>> trace, T e) {
        TreeNode<T> unBalanceNode = null;
        TreeNode<T> unBalNodeParent = null;
        TreeNode<T> n = null;
        while ((n = trace.peek()) != null && unBalanceNode == null) {
            n = trace.pop();
            n.height = calHeight(n);
            if (!n.isBalanced()) {
                unBalanceNode = n;
            }
        }
        if (trace.peek() != null) {
            unBalNodeParent = trace.pop();
        }
        // 平衡状态 返回
        if (unBalanceNode == null) {
            return;
        }
        // 确定插入方式
        int compareInt = unBalanceNode.element.compareTo(e);
        if (compareInt > 0) {
            if (calHeight(unBalanceNode.left.left) - calHeight(unBalanceNode.left.right) > 0) {
                rotateRight(unBalanceNode, unBalNodeParent);
            } else {
                // 先左旋时,视原非平衡节点的左儿子为非平衡节点
                rotateLeft(unBalanceNode.left, unBalanceNode);
                rotateRight(unBalanceNode, unBalNodeParent);
            }
        } else if (compareInt < 0) {
            if (calHeight(unBalanceNode.right.left) - calHeight(unBalanceNode.right.right) < 0) {
                rotateLeft(unBalanceNode, unBalNodeParent);
            } else {
                rotateRight(unBalanceNode.right, unBalanceNode);
                rotateLeft(unBalanceNode, unBalNodeParent);
            }
        }
        // 旋转完毕,旋转子树的高度信息已经更新过了,继续更新非平衡节点以上的高度信息
        while ((n = trace.peek()) != null) {
            n = trace.pop();
            n.height = calHeight(n);
        }
    }

    private void rotateRight(TreeNode<T> unBalanceNode, TreeNode<T> unBalNodeParent) {
        TreeNode<T> newRoot = unBalanceNode.left;
        TreeNode<T> ubParent = unBalNodeParent;
        // 周知树其余部分
        if (ubParent != null) {
            if (ubParent.left != null && ubParent.left.equals(unBalanceNode)) {
                ubParent.left = newRoot;
            } else {
                ubParent.right = newRoot;
            }
        } else {
            this.root = newRoot;
        }
        // 儿子移交
        if (newRoot.right != null) {
            unBalanceNode.left = newRoot.right;
        } else {
            unBalanceNode.left = null;
        }
        // 新根上任,左儿子无需处理
        newRoot.right = unBalanceNode;

        // 更新三个节点的高度信息
        unBalanceNode.height = calHeight(unBalanceNode);
        newRoot.height = calHeight(newRoot);
        if (ubParent != null) {
            ubParent.height = calHeight(ubParent);
        }
    }

    private void rotateLeft(TreeNode<T> unBalanceNode, TreeNode<T> unBalNodeParent) {
        TreeNode<T> newRoot = unBalanceNode.right;
        TreeNode<T> ubParent = unBalNodeParent;

        if (ubParent != null) {
            if (ubParent.left != null && ubParent.left.equals(unBalanceNode)) {
                ubParent.left = newRoot;
            } else {
                ubParent.right = newRoot;
            }
        } else {
            this.root = newRoot;
        }

        if (newRoot.left != null) {
            unBalanceNode.right = newRoot.left;
        } else {
            unBalanceNode.right = null;
        }

        newRoot.left = unBalanceNode;

        unBalanceNode.height = calHeight(unBalanceNode);
        newRoot.height = calHeight(newRoot);
        if (ubParent != null) {
            ubParent.height = calHeight(ubParent);
        }
    }

    private void insertNonRecursive0(T e, LinkedList<TreeNode<T>> trace) {
        TreeNode<T> node = new TreeNode<>(e);
        if (root == null) {
            root = node;
            root.height = 0;
            return;
        }
        TreeNode<T> current = root;
        trace.push(current);
        int compareInt = 0;
        while (true) {
            compareInt = current.element.compareTo(e);
            if (compareInt > 0) {
                if (current.left == null) {
                    current.left = node;
                    trace.push(node);
                    return;
                }
                current = current.left;
                trace.push(current);
            } else if (compareInt < 0) {
                if (current.right == null) {
                    current.right = node;
                    trace.push(node);
                    return;
                }
                current = current.right;
                trace.push(current);
            } else {
                // 相等 不插入
                return;
            }

        }
    }

    /**
     * 找最小节点
     *
     * @param root 根节点
     */
    private TreeNode<T> findMin(TreeNode<T> root) {
        if (root == null) {
            return null;
        } else if (root.left == null) {
            return root;
        }
        return findMin(root.left);
    }

    private void reBalanceAfterRemove(LinkedList<TreeNode<T>> trace, T e) {
        while (true) {
            TreeNode<T> n = null;
            TreeNode<T> unBalanceNode = null;
            TreeNode<T> unBalNodeParent = null;
            while ((n = trace.peek()) != null && unBalanceNode == null) {
                n = trace.pop();
                n.height = calHeight(n);
                if (!n.isBalanced()) {
                    unBalanceNode = n;
                }
            }

            // 平衡态
            if (unBalanceNode == null) {
                return;
            }

            unBalNodeParent = trace.peek();

            int compareInt = unBalanceNode.element.compareTo(e);

            // 被删除节点是不平衡节点的左儿子,则右子树高于左子树
            if (compareInt > 0) {
                // 如果不平衡节点的右儿子的左子树高于右子树,则需要先右后左双旋转(相当于右左插入)
                if (calHeight(unBalanceNode.right.left) - calHeight(unBalanceNode.right.right) > 0) {
                    rotateRight(unBalanceNode.right, unBalanceNode);
                    rotateLeft(unBalanceNode, unBalNodeParent);
                } else {
                    // 相等和小于的情况 都可以通过左旋平衡
                    rotateLeft(unBalanceNode, unBalNodeParent);
                }
            } else {
                // 相当于左右插入
                if (calHeight(unBalanceNode.left.left) - calHeight(unBalanceNode.left.right) < 0) {
                    rotateLeft(unBalanceNode.left, unBalanceNode);
                    rotateRight(unBalanceNode, unBalNodeParent);
                } else {
                    // 相等和大于的情况 都可以通过右旋平衡
                    rotateRight(unBalanceNode, unBalNodeParent);
                }
            }

            for (TreeNode<T> n1 : trace) {
                n1.height = calHeight(n1);
            }
        }
    }

    private boolean tryRemove(T e, LinkedList<TreeNode<T>> trace, TreeNode<T> current) {
        while (true) {
            int compareInt = current.element.compareTo(e);
            if (compareInt > 0) {
                if (current.left == null) {
                    // 没有找到节点 直接返回
                    return true;
                }
                current = current.left;
                trace.push(current);
            } else if (compareInt < 0) {
                if (current.right == null) {
                    // 没有找到节点
                    return true;
                }
                current = current.right;
                trace.push(current);
            } else {
                // 找到元素,情况一:该节点为叶子节点
                if (current.left == null && current.right == null) {
                    // 弹出被删除节点
                    trace.pop();
                    if (current == root) {
                        root = null;
                        return true;
                    }
                    TreeNode<T> parent = trace.peek();
                    // 查询父节点
                    if (parent.left == current) {
                        parent.left = null;
                        return true;
                    } else {
                        parent.right = null;
                        return true;
                    }
                }
                // 找到元素,情况二:该节点只有一个儿子

                if (current.left == null) {
                    trace.pop();// 弹出被删除节点
                    TreeNode<T> son = current.right;
                    if (current == root) {
                        root = son;
                        return true;
                    }
                    TreeNode<T> parent = trace.peek();
                    if (parent.left == current) {
                        parent.left = son;
                        return true;
                    } else {
                        parent.right = son;
                        return true;
                    }
                }

                if (current.right == null) {
                    trace.pop();// 弹出被删除节点
                    TreeNode<T> son = current.left;
                    if (current == root) {
                        root = son;
                        return true;
                    }
                    TreeNode<T> parent = trace.peek();
                    if (parent.left == current) {
                        parent.left = son;
                        return true;
                    } else {
                        parent.right = son;
                        return true;
                    }
                }
                // 找到节点,情况三:但是节点有两个儿子,返回false
                return false;
            }
        }
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值