AVL树 Java实现

还真是第一次用Java来实现一棵AVL树   要考虑方方面面啊   好累  写了2天    顺便复习一下AVL树    废话不多说  :

import java.nio.file.attribute.AclEntryType;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Created by albert.bai on 2014/11/6.
 * AVL树是一个带有平衡条件的平衡二叉树,他的左右子树都是平衡二叉树
 * 左右子树的高度差绝对值小于1;
 * 平衡因子:左子树高度减去右子树高度
 * 平衡二叉树是对二叉排序树的优化,防止二叉排序树在最坏情况下平均查找时间为n,
 * 二叉排序树最坏情况下形如一个单链表
 * 平衡二叉树查找元素的次数不超过树的深度,时间复杂度为logN;
 */
public class AVLTree<E> {
    private static final int LH = 1;
    private static final int EH = 0;
    private static final int RH = -1;

    static class Entry<E> {
        E element;
        Entry<E> parent;
        Entry<E> left;
        Entry<E> right;
        int balance = EH; //平衡因子,只能为1或0或-1

        public Entry(E element, Entry<E> parent) {
            this.element = element;
            this.parent = parent;
        }

        public Entry() {
        }

        @Override
        public String toString() {
            return element + "BF=" + balance;
        }
    }

    /**
     * 根节点
     */
    private Entry<E> root = null;
    /**
     * 树中元素个数
     */
    private int size = 0;

    public AVLTree() {

    }

    public int size() {
        return size;
    }

    /**
     * @param p 最小旋转树的根节点
     *          左旋后p移到p的左子树处,p的右子树B现在为根节点
     *          B的左子变为P的右子树
     */
    private void rotateLeft(Entry<E> p) {
        System.out.println("绕" + p + "左旋");
        if (p != null) {
            Entry<E> R = p.right;
            p.right = R.left;  //把p的右子树R 的左节点嫁接过来 不管是否为null
            if (R.left != null) {//如果R的左节点不为空  那么将其parent设置为P
                R.left.parent = p;
            }
            R.parent = p.parent; //R现在是根节点了 所以得将原来的根节点p的parent 嫁接给R
            if (p.parent == null) { //如果P的parent为null 那么R就是root了
                root = R;
            } else if (p.parent.left == p) {//如果p是p的parent的左子树  那么将p的parent的左子树嫁接给R
                p.parent.left = R;
            } else if (p.parent.right == p) {//同上
                p.parent.right = R;
            }
            R.left = p;//将p嫁接在R的左子树上
            p.parent = R;//当然现在p的parent变成了R了   狸猫换太子
        }

    }

    /**
     * @param p 最小旋转树的根节点
     *          右旋后p移到p的右子树上,p的左子树L现在为根节点
     *          L的右子树变为p的左子树
     */
    private void rotateRight(Entry<E> p) {
        System.out.println("绕" + p.element + "右旋");
        if (p != null) {
            Entry<E> L = p.left;
            p.left = L.right;
            if (L.right != null) { //如果L的右节点不是空的,那么将其parent设置为parent
                L.right.parent = p;
            }
            L.parent = p.parent;
            if (p.parent == null) {
                root = L;
            } else if (p.parent.left == p) {
                p.parent.left = L;
            } else
                p.parent.right = L;
            L.right = p;
            p.parent = L;
        }
    }

    /**
     * @param element 传入的节点
     * @return true/false
     * 1 像二叉搜索树那样,找到要插入的位置,并插入
     * 2 从下向上回溯:
     * a 修改平衡因子,当插入一个节点后只有root到插入节点的路径上的节点的平衡因子会发生改变
     * 当插入的节点在某节点A的左子树时,A的平衡因子为BF+1,右节点是为BF-1
     * 判断是在左右子树时只要通过比较其与A的大小比较
     * b 在改变平衡因子的同时,找到最近一个平衡因子>2或<2的节点,从这个节点开始调整祖先节点
     */
    public boolean add(E element) {
        Entry<E> t = root;
        if (t == null) {
            root = new Entry<E>(element, null);
            size = 1;
            return true;
        }
        int cmp;
        Entry<E> parent;//保存t的父节点
        Comparable<? super E> e = (Comparable<? super E>) element;
        //从根节点向下找,找到插入位置;
        do {
            parent = t;
            cmp = e.compareTo(t.element);
            if (cmp < 0) {
                t = t.left;
            } else if (cmp > 0) {
                t = t.right;
            } else {
                return false;
            }
        } while (t != null);
        Entry<E> child = new Entry(element, parent);
        if (cmp < 0) {
            parent.left = child;
        } else {
            parent.right = child;
        }
        //自下向上回溯,查找最近不平衡节点
        while (parent != null) {
            if (cmp < 0) {
                parent.balance++;
            } else {
                parent.balance--;
            }
            if (parent.balance == 0) {//此时balence为0  说明左右子树为等高 不需要调整
                break;
            }
            if ((Math.abs(parent.balance) == 2)) {
                fixAfterInsertion(parent);
                break;
            }
            parent = parent.parent;
        }
        size++;
        return true;
    }

    /**
     * 调整方法:
     * 1 当最小不平衡树的根R的balence为2是说明左子树高于右子树
     * 如果R的左子树的根节点BF为1时 右旋;
     * 如果R的左子树的根节点BF为-1时  先左旋在右旋;
     * 2 反正  亦然
     */
    private void fixAfterInsertion(Entry<E> p) {
        if (p.balance == 2) {
            leftBalence(p);
        }
        if (p.balance == -2) {
            rightBalence(p);
        }

    }

    private boolean leftBalence(Entry<E> t) {//左平衡
        boolean heightLower = true;
        Entry<E> l = t.left;
        switch (l.balance) {
            case LH://左高  ,右旋调整,旋转后树的高度减少
                t.balance = l.balance = EH;
                rotateRight(t);
                break;
            case RH://右高,分情况调整
                Entry<E> rd = l.right;
                switch (rd.balance) {
                    case LH:
                        t.balance = RH;
                        l.balance = EH;
                        break;
                    case EH:
                        t.balance = l.balance = EH;
                        break;
                    case RH:
                        t.balance = EH;
                        l.balance = LH;
                        break;
                }
                rd.balance = EH;
                rotateLeft(t.left);
                rotateRight(t);
                break;
            case EH://特殊情况 这种情况在添加时不可能发生,但在移除时可能发生
                l.balance = RH;
                t.balance = LH;
                rotateRight(t);
                heightLower = false;
                break;
        }
        return heightLower;
    }

    //反之亦然
    private boolean rightBalence(Entry<E> t) {
        boolean heightLower = true;
        Entry<E> r = t.right;
        switch (r.balance) {
            case LH:
                Entry<E> ld = r.left;
                switch (ld.balance) {
                    case LH:
                        t.balance = EH;
                        r.balance = RH;
                        break;
                    case EH:
                        t.balance = r.balance = EH;
                        break;
                    case RH:
                        t.balance = LH;
                        r.balance = EH;
                        break;
                }
                ld.balance = EH;
                rotateRight(t.right);
                rotateLeft(t);
                break;
            case RH:
                t.balance = r.balance = EH;
                rotateLeft(t);
                break;
            case EH:
                r.balance = LH;
                t.balance = RH;
                rotateLeft(t);
                heightLower = false;
                break;
        }
        return heightLower;
    }


    private Entry<E> getEntry(Object element) {
        Entry<E> temp = root;
        Comparable<? super E> e = (Comparable<? super E>) element;
        int cmp;
        while (temp != null) {
            cmp = e.compareTo(temp.element);
            if (cmp == 0) {
                return temp;
            } else if (cmp < 0) {
                temp = temp.left;
            } else {
                temp = temp.right;
            }
        }
        return null;
    }


    public boolean remove(Object o) {
        Entry<E> e = getEntry(o);
        if (e != null) {
            deleteEntry(e);
            return true;
        }
        return false;
    }


    private void deleteEntry(Entry<E> p) {
        size--;
        //如果p左右子树都不为空,找到其直接后继,替换p,之后p指向s,删除p就是删除s;
        if (p.left != null && p.right != null) {
            Entry<E> s = successor(p);
            p.element = s.element;
            p = s;
        }
        Entry<E> replacement = (p.left != null ? p.left : p.right);
        if (replacement != null) {//左右空其一
            replacement.parent = p.parent;
            if (p.parent == null) {
                root = replacement;
            } else if (p == p.parent.left) {
                p.parent.left = replacement;
            } else
                p.parent.right = replacement;
            p.left = p.right = p.parent = null;

            fixAfterDeletion(replacement);
        } else if (p.parent == null) {
            root = null;
        } else {//左右子树都是空的
            fixAfterDeletion(p);
            if (p.parent != null) {
                if (p == p.parent.left) {
                    p.parent.left = null;
                } else if (p == p.parent.right) {
                    p.parent.right = null;
                }
                p.parent = null;
            }
        }

    }

    /**
     * 中序遍历方式,找到t的直接后继
     *
     * @param t
     * @param <E>
     * @return
     */
    static <E> Entry<E> successor(Entry<E> t) {
        if (t == null) {
            return null;
        } else if (t.right != null) {
            Entry<E> p = t.right;
            while (p.left != null) {
                p = p.left;
            }
            return p;
        } else {
            Entry<E> p = t.parent;
            Entry<E> ch = t;
            while (p != null && ch == p.right) {
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

    private void fixAfterDeletion(Entry<E> p) {
        boolean heightLower = true;
        Entry<E> t = p.parent;
        Comparable<? super E> e = (Comparable<? super E>) p.element;
        int cmp;
        while (t != null && heightLower) {
            cmp = e.compareTo(t.element);
            if (cmp >= 0) {
                t.balance++;
            } else
                t.balance--;
            if (Math.abs(t.balance) == 1) {
                break;
            }
            Entry<E> r = t;
            if (t.balance == 2) {
                heightLower = leftBalence(r);
            } else if (t.balance == -2) {
                heightLower = rightBalence(r);
            }
            t = t.parent;
        }
    }

    private class BinarySortIterator implements Iterator<E> {
        Entry<E> next;
        Entry<E> lastReturned;

        public BinarySortIterator() {
            Entry<E> s = root;
            if (s != null) {
                while (s.left != null) {
                    s = s.left;
                }
                next = s;//中序遍历的第一个元素
            }
        }

        /**
         * Returns {@code true} if the iteration has more elements.
         * (In other words, returns {@code true} if {@link #next} would
         * return an element rather than throwing an exception.)
         *
         * @return {@code true} if the iteration has more elements
         */
        @Override
        public boolean hasNext() {
            return next != null;
        }

        /**
         * Returns the next element in the iteration.
         *
         * @return the next element in the iteration
         * @throws NoSuchElementException if the iteration has no more elements
         */
        @Override
        public E next() {
            Entry<E> e = next;
            if (e == null) {
                throw new NoSuchElementException();
            }
            next = successor(e);
            lastReturned = e;

            return e.element;
        }

        /**
         * Removes from the underlying collection the last element returned
         * by this iterator (optional operation).  This method can be called
         * only once per call to {@link #next}.  The behavior of an iterator
         * is unspecified if the underlying collection is modified while the
         * iteration is in progress in any way other than by calling this
         * method.
         *
         * @throws UnsupportedOperationException if the {@code remove}
         *                                       operation is not supported by this iterator
         * @throws IllegalStateException         if the {@code next} method has not
         *                                       yet been called, or the {@code remove} method has already
         *                                       been called after the last call to the {@code next}
         *                                       method
         */
        @Override
        public void remove() {
            if (lastReturned == null) {
                throw new IllegalStateException();
            }
            if (lastReturned.left != null && lastReturned.right != null) {
                next = lastReturned;
                deleteEntry(lastReturned);
                lastReturned = null;
            }

        }
    }

    public Iterator<E> iterator() {
        return new BinarySortIterator();
    }

    private int treeHeight(Entry<E> p) {
        if (p == null) {
            return -1;
        }
        return 1 + Math.max(treeHeight(p.left), treeHeight(p.right));
    }

    public static void main(String[] args) {
        AVLTree<Integer> avlTree = new AVLTree<Integer>();
        avlTree.add(23);
        avlTree.add(34);
        avlTree.add(56);
        avlTree.add(12);
        avlTree.add(87);
        Iterator<Integer> it = avlTree.iterator();
        while (it.hasNext()) {

//            it.remove();
            System.out.println(it.next());

        }
        avlTree.remove(23);
        Iterator<Integer> it2 = avlTree.iterator();
        while (it2.hasNext()) {
            System.out.println(it2.next());
        }
    }
}
    原文作者:AVL树
    原文地址: https://blog.csdn.net/alber_twhite/article/details/41172559
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞