数据结构--平衡二叉树

1、基本概念

平衡二叉树(AVL树)是一种二叉排序树,其中每个节点的左子树和右子树的高度最多相差1
平衡因子:二叉树的左子树深度减去右子树的深度 只有-1,0,1三个值
最小不平衡子树:距离插入节点最近,且平衡因子的绝对值大于1的节点为根节点

2、实现

在构建二叉排序树的过程中,每当插入一个节点,先检查是否因插入的新数据破坏了平衡性 若是 找出最小不平衡子树。在保持排序二叉树特性的情况下,调整最小不平衡子树中各节点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。

平衡二叉树就是一个二叉排序树,只不过需要保证左右子树的深度在正负1以内,保证深度,就是做树的左右旋转操作

static class AVLNode{
    int data;
    int height; //节点的深度
    AVLNode left, right;

    public AVLNode(int data){
        this.data = data;
        left = null;
        right = null;
    }
}

//测试
public static void main(String[] args) {
    int[] src = { 3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9 };

    AVLNode root = null;
    for (int i = 0; i < src.length; i++) {
        root = insert(root, src[i]);
    }

    print(root);
    System.out.println("----------------------");

    remove(root, 15);

    print(root);
}

//获取节点的高度
public static int height(AVLNode node){
    if(node != null)
        return node.height;
    return 0;
}

//左旋转
public static AVLNode llRotate(AVLNode node){
    AVLNode tmp = node.left;
    node.left = tmp.right;
    tmp.right = node;
    node = tmp;

    node.height = Math.max(height(node.left), height(node.right))+1;
    tmp.height = Math.max(height(tmp.left), height(node))+1;

    return tmp;
}

//右旋转
public static AVLNode rrRotate(AVLNode node){
    AVLNode tmp = node.right;
    node.right = tmp.left;
    tmp.left = node;

    node.height = Math.max(height(node.left), height(node.right))+1;
    tmp.height = Math.max(height(tmp.right), height(node))+1;

    return tmp;
}

//先左旋转 再右旋转
public static AVLNode lrRotate(AVLNode node){
    node.left = rrRotate(node.left);
    return llRotate(node);
}

//先右旋转 再左旋转
public static AVLNode rlRotate(AVLNode node){
    node.right = llRotate(node.right);
    return rrRotate(node);
}

//插入操作
public static AVLNode insert(AVLNode node, int data) {
    if(node == null) {//新建节点
        node = new AVLNode(data);
    } else {
        if(data < node.data) {  //插入左子树
            node.left = insert(node.left, data);
            //如果排序二叉树不平衡
            if(height(node.left) - height(node.right) == 2)
                //当前节点在左子树,当前节点的data比上一个节点小 表示上一个节点也是左子树 所以直接左转换
                if(data < node.left.data)
                    node = llRotate(node);
                else
                    //当前节点比上一个节点大 表示上一个节点是右子树
                    node = lrRotate(node);
        }else if (data > node.data) {
            node.right = insert(node.right, data);
            if(height(node.right) - height(node.left) == 2)
                if(data > node.right.data)
                    node = rrRotate(node);
                else
                    node = rlRotate(node);
        }else
            ;
    }

    if(node != null)
        //回溯,使节点深度每次+1
        node.height = Math.max(height(node.left), height(node.right))+1;

    return node;
}

public static AVLNode remove(AVLNode node, int data){
    if(node == null)
        return null;

    if(data < node.data) {  //左子树
        node.left = remove(node.left, data);
        if(height(node.right) - height(node.left) == 2) {   //如果失去平衡
            AVLNode r =  node.right;    //右子树高度大 旋转右子树 使平衡因子小于2
            if (height(r.right) > height(r.left))
                node = rlRotate(node);
            else
                node = rrRotate(node);
        }
    } else if(data > node.data) {   //右子树
        node.right = remove(node.right, data);
        if(height(node.left) - height(node.right) == 2) {
            AVLNode l =  node.left;
            if (height(l.right) > height(l.left))
                node = lrRotate(node);
            else
                node = llRotate(node);
        }
    } else if(node.left!=null && node.right!=null) {
        //如果左子树的深度大于右子树,则使用左子树的最大值替换
        if(height(node.left) > height(node.right)) {
            node.data = findMax(node.left).data;
            node.left = remove(node.left, node.data);
        } else {
            //否则使用右子树的最小值替换
            node.data = findMin(node.right).data;
            node.right = remove(node.right, node.data);
        }
    } else {
        node = (node.left != null) ? node.left : node.right;
    }

    return node;
}

//查找树中的最小值
public static AVLNode findMin(AVLNode node){
    if(node == null)
        return null;
    else if(node.left == null)
        return node;
    else
        return findMin(node.left);//最左边的是最小的
}

//查找树中的最大值
public static AVLNode findMax(AVLNode node){
    if(node == null)
        return null;
    else if(node.right == null)
        return node;
    else
        return findMax(node.right);//最右边的是最大的
}

//中序遍历
public static void print(AVLNode node){
    if(node != null) {
        print(node.left);

        System.out.println(node.data + "  "+node.height);

        print(node.right);
    }
}

参考:
http://www.cnblogs.com/skywang12345/p/3577479.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值