AVL实现

   日期:2020-05-08     浏览:103    评论:0    
核心提示:前言:前面是Avl树的介绍写的比较详细,这一篇主要写怎么实现最简单的旋转依次插入1 2 3节点,1的数据结构与算法

前言:

前面是Avl树的介绍写的比较详细,这一篇主要写怎么实现

最简单的旋转

依次插入1 2 3节点,1的左子树为空高度为0,而右子树高度为2,旋转后,左右高度都为1

单旋转

依次插入6 3 7 1 4,插入2时,树的平衡被破坏

步骤:

获取k1节点=k2的左边节点
设置k2的左边节点为k1的右边节点Y
设置k1的右边节点为k2
重新计算k2和k1的高度

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

双旋转

依次插入6 2 7 1 4,插入3时,树的平衡被破坏

下面的图解C节点实际上应该没有,因为插入B的时候已经影响平衡

步骤:

k3的左边子树进行一次右边的单旋转
k3进行一次左边的单旋转

 private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

实现

平衡二叉树实现的大部分过程和二叉查找树是一样的,区别就在于插入和删除之后要判断树左右子树高度之差是否大于1,如果大于1需要进行旋转维持平衡
其它的两种插入影响平衡的情况和以上两种刚好相反

代码

树节点

package 二叉树;
public class AvlNode<T> {
    T element;
    int height;
    AvlNode<T> left;
    AvlNode<T> right;

    public AvlNode(T element) {
        this(element, null, null);
    }

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

平衡代码

private AvlNode<T> balance(AvlNode<T> t) {
        if (t == null) {
            return t;
        }

        if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
            if (height(t.left.left) >= height(t.left.right)) {
                t = rotateWithLeftChild(t);
            } else {
                t = doubleWithLeftChild(t);
            }
        } else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
            if (height(t.right.right) >= height(t.right.left)) {
                t = rotateWithRightChild(t);
            } else {
                t = doubleWithRightChild(t);
            }
        }
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }

完整代码

package 二叉树;


public class AvlTree<T extends Comparable<? super T>> {

    private AvlNode<T> root;

    public void insert(T x) {
        root = insert(x, root);
    }

    public void remove(T x) {
        root = remove(x, root);
    }

    public T findMin() {
        return findMin(root).element;
    }


    public void makeEmpty() {
        root = null;
    }

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

    
    private AvlNode<T> insert(T x, AvlNode<T> t) {

        //如果根节点为空,则当前x节点为根及诶单
        if (null == t) {
            return new AvlNode(x);
        }

        int compareResult = x.compareTo(t.element);

        //小于当前根节点 将x插入根节点的左边
        if (compareResult < 0) {
            t.left = insert(x, t.left);
        } else if (compareResult > 0) {
            //大于当前根节点 将x插入根节点的右边
            t.right = insert(x, t.right);
        } else {

        }
        return balance(t);
    }

    private static final int ALLOWED_IMBALANCE = 1;

    private AvlNode<T> balance(AvlNode<T> t) {
        if (t == null) {
            return t;
        }

        if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
            if (height(t.left.left) >= height(t.left.right)) {
                t = rotateWithLeftChild(t);
            } else {
                t = doubleWithLeftChild(t);
            }
        } else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
            if (height(t.right.right) >= height(t.right.left)) {
                t = rotateWithRightChild(t);
            } else {
                t = doubleWithRightChild(t);
            }
        }
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }

    private AvlNode<T> doubleWithRightChild(AvlNode<T> k3) {
        k3.right = rotateWithLeftChild(k3.right);
        return rotateWithRightChild(k3);
    }

    private AvlNode<T> rotateWithRightChild(AvlNode<T> k2) {
        AvlNode k1 = k2.right;
        k2.right = k1.left;
        k1.left = k2;
        k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
        k1.height = Math.max(height(k1.right), k2.height) + 1;
        return k1;
    }

    private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

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

    private int height(AvlNode<T> t) {
        return t == null ? -1 : t.height;
    }

    
    private AvlNode<T> remove(T x, AvlNode<T> t) {

        if (null == t) {
            return t;
        }

        int compareResult = x.compareTo(t.element);

        //小于当前根节点
        if (compareResult < 0) {
            t.left = remove(x, t.left);
        } else if (compareResult > 0) {
            //大于当前根节点
            t.right = remove(x, t.right);
        } else if (t.left != null && t.right != null) {
            //找到右边最小的节点
            t.element = findMin(t.right).element;
            //当前节点的右边等于原节点右边删除已经被选为的替代节点
            t.right = remove(t.element, t.right);
        } else {
            t = (t.left != null) ? t.left : t.right;
        }
        return balance(t);
    }

    
    private AvlNode<T> findMin(AvlNode<T> root) {
        if (root == null) {
            return null;
        } else if (root.left == null) {
            return root;
        }
        return findMin(root.left);
    }

    
    private AvlNode<T> findMax(AvlNode<T> root) {
        if (root == null) {
            return null;
        } else if (root.right == null) {
            return root;
        } else {
            return findMax(root.right);
        }
    }

    public void printTree() {
        if (isEmpty()) {
            System.out.println("节点为空");
        } else {
            printTree(root);
        }
    }


    public void printTree(AvlNode<T> root) {
        if (root != null) {
            System.out.print(root.element);
            if (null != root.left) {
                System.out.print("左边节点" + root.left.element);
            }
            if (null != root.right) {
                System.out.print("右边节点" + root.right.element);
            }
            System.out.println();
            printTree(root.left);
            printTree(root.right);
        }


    }

}

测试

package 二叉树;

public class Test{
    public static void main (String[] args) {
            AvlTree testTree = new AvlTree();
            testTree.insert(36);
            testTree.insert(22);
            testTree.insert(16);
            testTree.insert(45);
            testTree.insert(28);
            testTree.insert(60);

            testTree.printTree();


    }
}

欢迎大家关注公众号:小黄爱编程

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服