yangbo i need a girlfriend ^-^

平衡二叉树

2017-05-10
yangbo

平衡二叉树,递归实现

结构

由于二叉查找树插入删除操作,会导致树的不平衡,所有需要自己平衡,即平衡二叉树,

左边的是平衡二叉树,右边的则不平衡,树2的高度比树8高2,平衡条件是不超过1.

所以需要对数旋转以达到平衡。

class AVLTreeNode<E extends Comparable<E>>{
        E data;
        AVLTreeNode left;
        AVLTreeNode right;
        int height;

         AVLTreeNode(E e) {
            this(e,null,null);
        }

         AVLTreeNode(E e, AVLTreeNode<E> lt, AVLTreeNode<E> rt) {
            data = e;
            left = lt;
            right = rt;
            height = 0;
        }
    }

计算节点高度方法

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

旋转

总共有四种情况

1对节点的左儿子的左儿子进行插入

2对节点的左儿子的右儿子进行插入

3对节点的右儿子的左儿子进行插入

4对节点的右儿子的右儿子进行插入

情况1,4对称,2,3对称

单旋转:左左,右右

左左的情况旋转如图,

右右的情况对称

左左:

 private AVLTreeNode<E> rotateWithLeftChild(AVLTreeNode<E> k2) {
        AVLTreeNode<E> 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 AVLTreeNode rotateWithRightChild(AVLTreeNode<E> k2) {
        AVLTreeNode<E> 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;
    }

双旋转:左右,右左

上图为左右的平衡,先k3左子树右右单旋转,再k3左左单旋转,

右左的情况对称

左右:

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

右左:

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

平衡方法

 private AVLTreeNode<E> balance(AVLTreeNode<E> t) {
        if (t == null){
            return t;
        }
        if (height(t.left) - height(t.right) > h){
            if (height(t.left.left) >= height(t.left.right)){
                //左左
                t = rotateWithLeftChild(t);
            }else {
                //左右
                t = doubleWithLeftChild(t);
            }
        }else{
            if (height(t.right) - height(t.left) > h){
              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;
    }

insert

每次插入后都需要平衡

private AVLTreeNode<E> insert(E e, AVLTreeNode<E> t){
        if (t == null){
            return new AVLTreeNode<E>(e,null,null);
        }
        int result = e.compareTo(t.data);
        if (result < 0){
            t.left = insert(e, t.left);
        }else if (result > 0){
            t.right = insert(e, t.right);
        }else {

        }
        return balance(t);
    }

remove

删除跟二叉查找树一样,每次删除后都需要平衡

private AVLTreeNode<E> remove(E e, AVLTreeNode<E> t){
        if (t == null){
            return t;
        }
        int result = e.compareTo(t.data);
        if (result < 0){
            t.left = remove(e, t.left);
        }else if (result > 0){
            t.right = remove(e, t.right);
        }else if (t.left != null && t.right != null){
            t.data = (E) findMin(t.right).data;
            t.right = remove(t.data, t.right);
        }else {
            t = (t.left != null) ? t.left : t.right;
        }
        return balance(t);
    }

具体实现

package com.yb.shujujiegou.shu;

/**
 * Created by 杨波 on 2017/5/9.
 */
public class AVLBinaryTree<E extends Comparable<E>> {
    private static class AVLTreeNode<E extends Comparable<E>>{
        E data;
        AVLTreeNode left;
        AVLTreeNode right;
        int height;

         AVLTreeNode(E e) {
            this(e,null,null);
        }

         AVLTreeNode(E e, AVLTreeNode<E> lt, AVLTreeNode<E> rt) {
            data = e;
            left = lt;
            right = rt;
            height = 0;
        }
    }
    private AVLTreeNode<E> root = null;
    //计算节点高度
    private int height(AVLTreeNode<E> t){
        return t == null ? -1 : t.height;
    }
    //插入
    private AVLTreeNode<E> insert(E e, AVLTreeNode<E> t){
        if (t == null){
            return new AVLTreeNode<E>(e,null,null);
        }
        int result = e.compareTo(t.data);
        if (result < 0){
            t.left = insert(e, t.left);
        }else if (result > 0){
            t.right = insert(e, t.right);
        }else {

        }
        return balance(t);
    }
    //平衡最大差
    private static  final int h = 1;
    //平衡
    private AVLTreeNode<E> balance(AVLTreeNode<E> t) {
        if (t == null){
            return t;
        }
        if (height(t.left) - height(t.right) > h){
            if (height(t.left.left) >= height(t.left.right)){
                //左左
                t = rotateWithLeftChild(t);
            }else {
                //左右
                t = doubleWithLeftChild(t);
            }
        }else{
            if (height(t.right) - height(t.left) > h){
              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 AVLTreeNode<E> doubleWithRightChild(AVLTreeNode<E> k3) {
        k3.right = rotateWithLeftChild(k3.right);
        return rotateWithRightChild(k3);
    }

    //左右(双旋转,先左子树右右单旋转,再左左单旋转)
    private AVLTreeNode<E> doubleWithLeftChild(AVLTreeNode<E> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }
    //右右(单旋转)
    private AVLTreeNode rotateWithRightChild(AVLTreeNode<E> k2) {
        AVLTreeNode<E> 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 AVLTreeNode<E> rotateWithLeftChild(AVLTreeNode<E> k2) {
        AVLTreeNode<E> 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;
    }
    public void insert(E e){
        root = insert(e, root);
    }
    //遍历:中序
    private void display(AVLTreeNode<E> avlTreeNode){
        if (avlTreeNode!=null){
            display(avlTreeNode.left);
            System.out.print(avlTreeNode.data+" ");
            display(avlTreeNode.right);
        }
    }
    public void display(){
        display(root);
    }
    //删除,每次删除都要平衡一次
    private AVLTreeNode<E> remove(E e, AVLTreeNode<E> t){
        if (t == null){
            return t;
        }
        int result = e.compareTo(t.data);
        if (result < 0){
            t.left = remove(e, t.left);
        }else if (result > 0){
            t.right = remove(e, t.right);
        }else if (t.left != null && t.right != null){
            t.data = (E) findMin(t.right).data;
            t.right = remove(t.data, t.right);
        }else {
            t = (t.left != null) ? t.left : t.right;
        }
        return balance(t);
    }

    private AVLTreeNode<E> findMin(AVLTreeNode<E> t) {
        if (t == null){
            return null;
        }else if (t.left == null){
            return t;
        }
        return findMin(t.left);
    }
    public void remove(E e){
        root = remove(e, root);
    }
    public static void main(String[] args) {
        AVLBinaryTree<Integer> avlBinaryTree = new AVLBinaryTree<Integer>();
        avlBinaryTree.insert(3);
        avlBinaryTree.insert(2);
        avlBinaryTree.insert(1);
        avlBinaryTree.insert(4);
        avlBinaryTree.insert(5);
        avlBinaryTree.remove(1);
        avlBinaryTree.display();
        avlBinaryTree.remove(4);
        System.out.println();
        avlBinaryTree.display();
    }
}


相似文章

上一篇 二叉树

下一篇 简单链表

评论