AVL树----java

                                                                                    AVL树----java

AVL树是高度平衡的二叉查找树

1.单旋转LL旋转

理解记忆:1.在不平衡的节点的左孩子的左孩子插入导致的不平衡,所以叫LL

private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> k2) {
    AVLTreeNode<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;
}

2.单旋转RR

理解记忆:1.不平衡节点的右孩子的有孩子插入导致的不平衡,所以叫RR

private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k1) {
    AVLTreeNode<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;
}

3.双旋转LR

理解记忆:1.不平衡节点的左孩子的有孩子导致的不平衡,所以叫LR

2.需要先对k1  RR,再对根K3  LL

private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {
    k3.left = rightRightRotation(k3.left);

    return leftLeftRotation(k3);
}

4.双旋转RL

理解记忆:1.不平衡节点的右孩子的左孩子导致的不平衡,所以叫RL

2.需要先对k3 LL,在对k1 RR

private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {
    k1.right = leftLeftRotation(k1.right);

    return rightRightRotation(k1);
}

5.AVL的例子

遍历,查找等和二叉查找树一样就不在列出,主要是 插入
 删除

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

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

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

    // 构造函数
    public AVLTree() {
        mRoot = null;
    }

    /*
     * 获取树的高度
     */
    private int height(AVLTreeNode<T> tree) {
        if (tree != null)
            return tree.height;

        return 0;
    }

    public int height() {
        return height(mRoot);
    }

    /*
     * 比较两个值的大小
     */
    private int max(int a, int b) {
        return a>b ? a : b;
    }

    /*
     * 前序遍历"AVL树"
     */
    private void preOrder(AVLTreeNode<T> tree) {
        if(tree != null) {
            System.out.print(tree.key+" ");
            preOrder(tree.left);
            preOrder(tree.right);
        }
    }

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

    /*
     * 中序遍历"AVL树"
     */
    private void inOrder(AVLTreeNode<T> tree) {
        if(tree != null)
        {
            inOrder(tree.left);
            System.out.print(tree.key+" ");
            inOrder(tree.right);
        }
    }

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

    /*
     * 后序遍历"AVL树"
     */
    private void postOrder(AVLTreeNode<T> tree) {
        if(tree != null) {
            postOrder(tree.left);
            postOrder(tree.right);
            System.out.print(tree.key+" ");
        }
    }

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

    /*
     * (递归实现)查找"AVL树x"中键值为key的节点
     */
    private AVLTreeNode<T> search(AVLTreeNode<T> x, T key) {
        if (x==null)
            return x;

        int cmp = key.compareTo(x.key);
        if (cmp < 0)
            return search(x.left, key);
        else if (cmp > 0)
            return search(x.right, key);
        else
            return x;
    }

    public AVLTreeNode<T> search(T key) {
        return search(mRoot, key);
    }

    /*
     * (非递归实现)查找"AVL树x"中键值为key的节点
     */
    private AVLTreeNode<T> iterativeSearch(AVLTreeNode<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 AVLTreeNode<T> iterativeSearch(T key) {
        return iterativeSearch(mRoot, key);
    }

    /*
     * 查找最小结点:返回tree为根结点的AVL树的最小结点。
     */
    private AVLTreeNode<T> minimum(AVLTreeNode<T> tree) {
        if (tree == null)
            return null;

        while(tree.left != null)
            tree = tree.left;
        return tree;
    }

    public T minimum() {
        AVLTreeNode<T> p = minimum(mRoot);
        if (p != null)
            return p.key;

        return null;
    }

    /*
     * 查找最大结点:返回tree为根结点的AVL树的最大结点。
     */
    private AVLTreeNode<T> maximum(AVLTreeNode<T> tree) {
        if (tree == null)
            return null;

        while(tree.right != null)
            tree = tree.right;
        return tree;
    }

    public T maximum() {
        AVLTreeNode<T> p = maximum(mRoot);
        if (p != null)
            return p.key;

        return null;
    }

    /*
     * LL:左左对应的情况(左单旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> k2) {
        AVLTreeNode<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;
    }

    /*
     * RR:右右对应的情况(右单旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k1) {
        AVLTreeNode<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;
    }

    /*
     * LR:左右对应的情况(左双旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {
        k3.left = rightRightRotation(k3.left);

        return leftLeftRotation(k3);
    }

    /*
     * RL:右左对应的情况(右双旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {
        k1.right = leftLeftRotation(k1.right);

        return rightRightRotation(k1);
    }

    /*
     * 将结点插入到AVL树中,并返回根节点
     *
     * 参数说明:
     *     tree AVL树的根结点
     *     key 插入的结点的键值
     * 返回值:
     *     根节点
     */
    private AVLTreeNode<T> insert(AVLTreeNode<T> tree, T key) {
        if (tree == null) {
            // 新建节点
            tree = new AVLTreeNode<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的左子树"的情况
                tree.left = insert(tree.left, key);
                // 插入节点后,若AVL树失去平衡,则进行相应的调节。
                if (height(tree.left) - height(tree.right) == 2) {
                    if (key.compareTo(tree.left.key) < 0)
                        tree = leftLeftRotation(tree);
                    else
                        tree = leftRightRotation(tree);
                }
            } else if (cmp > 0) {    // 应该将key插入到"tree的右子树"的情况
                tree.right = insert(tree.right, key);
                // 插入节点后,若AVL树失去平衡,则进行相应的调节。
                if (height(tree.right) - height(tree.left) == 2) {
                    if (key.compareTo(tree.right.key) > 0)
                        tree = rightRightRotation(tree);
                    else
                        tree = rightLeftRotation(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);
    }

    /*
     * 删除结点(z),返回根节点
     *
     * 参数说明:
     *     tree AVL树的根结点
     *     z 待删除的结点
     * 返回值:
     *     根节点
     */
    private AVLTreeNode<T> remove(AVLTreeNode<T> tree, AVLTreeNode<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) {
                AVLTreeNode<T> r =  tree.right;
                if (height(r.left) > height(r.right))
                    tree = rightLeftRotation(tree);
                else
                    tree = rightRightRotation(tree);
            }
        } else if (cmp > 0) {    // 待删除的节点在"tree的右子树"中
            tree.right = remove(tree.right, z);
            // 删除节点后,若AVL树失去平衡,则进行相应的调节。
            if (height(tree.left) - height(tree.right) == 2) {
                AVLTreeNode<T> l =  tree.left;
                if (height(l.right) > height(l.left))
                    tree = leftRightRotation(tree);
                else
                    tree = leftLeftRotation(tree);
            }
        } else {    // tree是对应要删除的节点。
            // tree的左右孩子都非空
            if ((tree.left!=null) && (tree.right!=null)) {
                if (height(tree.left) > height(tree.right)) {
                    // 如果tree的左子树比右子树高;
                    // 则(01)找出tree的左子树中的最大节点
                    //   (02)将该最大节点的值赋值给tree。
                    //   (03)删除该最大节点。
                    // 这类似于用"tree的左子树中最大节点"做"tree"的替身;
                    // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
                    AVLTreeNode<T> max = maximum(tree.left);
                    tree.key = max.key;
                    tree.left = remove(tree.left, max);
                } else {
                    // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
                    // 则(01)找出tree的右子树中的最小节点
                    //   (02)将该最小节点的值赋值给tree。
                    //   (03)删除该最小节点。
                    // 这类似于用"tree的右子树中最小节点"做"tree"的替身;
                    // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
                    AVLTreeNode<T> min = maximum(tree.right);
                    tree.key = min.key;
                    tree.right = remove(tree.right, min);
                }
            } else {
                AVLTreeNode<T> tmp = tree;
                tree = (tree.left!=null) ? tree.left : tree.right;
                tmp = null;
            }
        }

        return tree;
    }

    public void remove(T key) {
        AVLTreeNode<T> z; 

        if ((z = search(mRoot, key)) != null)
            mRoot = remove(mRoot, z);
    }

    /*
     * 销毁AVL树
     */
    private void destroy(AVLTreeNode<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);
    }

    /*
     * 打印"二叉查找树"
     *
     * key        -- 节点的键值
     * direction  --  0,表示该节点是根节点;
     *               -1,表示该节点是它的父结点的左孩子;
     *                1,表示该节点是它的父结点的右孩子。
     */
    private void print(AVLTreeNode<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);
    }
}

文章大量参考:http://www.cnblogs.com/skywang12345/p/3577479.html

AVL树----java,布布扣,bubuko.com

时间: 2024-12-07 08:04:41

AVL树----java的相关文章

AVL树(Java实现)

AVL树基本操作 未完....待续.... AVL树代码 public class AVLTree<Key extends Comparable<? super Key>, Value> { private class Node { Key key;//键,相当于词典里的单词 Value value;//值,相当于词典里的单词解释 int height;//结点的高度 Node left; Node right; public Node(Key key, Value value)

AVL树原理及实现(C语言实现以及Java语言实现)

欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好是按照从小到大的顺序或者从大到小的顺序插入的,那么搜索二叉树就对退化成链表,这个时候查找,插入和删除的时间都会上升到O(n),而这对于海量数据而言,是我们无法忍受的.即使是一颗由完全随机的数据构造成的搜索二叉树,从统计角度去分析,在进行若甘次的插入和删除操作,这个搜索二叉树的高度也不能令人满意.这个

平衡二叉搜索树(AVL树)的原理及实现源代码(有图文详解和C++、Java实现代码)

一.AVL树(平衡二叉搜索树)是什么? AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的.AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个非叶子结点的左右子树的高度之差的绝对值(平衡因子)最多为1. 例如: 5             5 / \            /  \ 2   6         2   6 / \    \         / \ 1  4   7       1  4

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

二叉树、二叉搜索树、AVL树的java实现

数据结构一直都是断断续续的看,总是觉得理解的不够深入,特别是对树的理解,一直都很浅显,今儿又看了一遍,来做个总结吧. 首先,树中的一些概念: 1.树的节点包含一个数据元素,以及若干指向其子树的分支.节点拥有的子树的数量称为节点的度.节点的最大层次称为树的深度或高度. 2.二叉树是一种树形结构,其特点是每个节点至多有两棵子树,且子树有左右之分,次序不能随意颠倒. 3.满二叉树:一棵深度为k且有2^k - 1个节点的二叉树,称之为满二叉树. 4.完全二叉树:对一个深度为k,节点个数为n的二叉树,当且

Java创建AVL树

AVL树是带有平衡条件的二叉查找树,其查找和删除的时间复杂度为logn,是对二叉查找树的改进,我们将节点的左子树和右子树深度之差称为平衡因子(BF),其中的每一个节点的平衡因子的绝对值不大于1. 距离插入节点最近的,并且平衡因子绝对值大于1的节点为根的子树,称为最小不平衡子树. 要实现AVL树,就必须保证在插入的时候消除不平衡的子树,即通过某种方式,使每次插入一个节点,都是平衡的BST树,下面我们讨论一下插入的时候四种情况: 1:对左孩子的左子树进行一次插入: 2:对左孩子的右子树进行一次插入:

AVL树-自平衡二叉查找树(Java实现)

在计算机科学中,AVL树是最先发明的自平衡二叉查找树.AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An algorithm for the organization of information" 中发表了它. 一.AVL树的旋转规律 AVL树的基本操作一般涉及运做同在不平衡的二叉查找树所运做的同样的算法.但是要进行预先或随后做一次或多次所谓的"AVL旋转". 假设由于在二叉排序树上插入

AVL树的JAVA实现及AVL树的旋转算法

1,AVL树又称平衡二叉树,它首先是一颗二叉查找树,但在二叉查找树中,某个结点的左右子树高度之差的绝对值可能会超过1,称之为不平衡.而在平衡二叉树中,任何结点的左右子树高度之差的绝对值会小于等于 1. 2,为什么需要AVL树呢?在二叉查找树中最坏情况下查找某个元素的时间复杂度为O(n),而AVL树能保证查找操作的时间复杂度总为O(logn). 3,AVL树的JAVA代码实现: AVLTree  继承 BinarySearchTree 并改写 添加节点的add方法,在add方法中判断插入元素后是否

数据结构--AVL树的insert()的Java实现

一个AVL树是其每个节点的左子树和右子树的高度差最多差1的二叉查找树:AVL树是一种最古老的平衡查找树 上代码: package com.itany.avlshu; public class AVLTree<T extends Comparable<?super T>> { private static class AvlNode<T> { private int height; private T element; private AvlNode<T> l