AVL树的插入

public class AVLTree {
    public AVLNode root = null;
    public int size = 0;    // 保存树的结点个数

    public void insert(long key) {
        AVLNode node = new AVLNode();
        node.key = key;
        node.left = null;
        node.right = null;
        node.parent = null;
        node.bf = 0;

        if (root == null) {
            root = node;
            size++;
            return;
        }

        AVLNode current = root;
        AVLNode parent = null;
        while (current != null) {
            if (key == current.key) {
                return;
                //throw new RuntimeException("插入失败,key 有重复: " + key);
            } else if (key < current.key) {
                parent = current;
                current = current.left;
            } else {
                parent = current;
                current = current.right;
            }
        }

        node.parent = parent;
        if (key < parent.key) {
            parent.left = node;
        } else {
            parent.right = node;
        }

        avlAdjust(parent, node);

        size++;
    }

    private void avlAdjust(AVLNode parent, AVLNode node) {
        // parent != null && node != null

        while (true) {
            // 进行平衡因子的调整
            if (node == parent.left) {
                parent.bf++;
            } else {
                parent.bf--;
            }

            // 第一种情况
            if (parent.bf == 0) {
                return;
            }

            // 第二种情况
            if (parent.bf == -1 || parent.bf == 1) {
                node = parent;
                parent = parent.parent;

                if (parent == null) {
                    // 向上回溯到根的位置了
                    return;
                }
                continue;
            }

            // 情况三
            // parent.bf == -2 || parent.bf == 2
            break;
        }

        // 一定是出现失衡情况了
        if (parent.bf == 2) {
            if (node.bf == 1) {
                // LL 失衡
                rightRotate(parent);

                parent.bf = node.bf = 0;
            } else {
                // LR 失衡
                // node.bf == -1
                AVLNode c = node.right;
                int condition;
                if (parent.right == null) {
                    condition = 1;
                } else if (c.bf == 1) {
                    condition = 2;
                } else {
                    condition = 3;
                }

                leftRotate(node);
                rightRotate(parent);

                if (condition == 1) {
                    parent.bf = node.bf = c.bf = 0;
                } else if (condition == 2) {
                    parent.bf = -1;
                    node.bf = c.bf = 0;
                } else {
                    parent.bf = c.bf = 0;
                    node.bf = 1;
                }
            }
        } else {
            // parent.bf == -2
            if (node.bf == -1) {
                // RR 失衡
                leftRotate(parent);

                parent.bf = node.bf = 0;
            } else {
                // RL 失衡
                // node.bf == 1

                AVLNode c = node.left;
                int condition;
                if (parent.left == null) {
                    condition = 1;
                } else if (c.bf == 1) {
                    condition = 2;
                } else {
                    condition = 3;
                }

                rightRotate(node);
                leftRotate(parent);

                if (condition == 1) {
                    parent.bf = node.bf = 0;
                } else if (condition == 2) {
                    parent.bf = c.bf = 0;
                    node.bf = -1;
                } else {
                    parent.bf = 1;
                    node.bf = c.bf = 0;
                }
            }
        }
    }

    // 以 m 为结点,进行左旋转
    private void leftRotate(AVLNode node) {
        // m 代表图中的 b 结点
        // parent 代表 b 结点可能存在的父亲
        AVLNode parent = node.parent;
        // right 代表图中的 a 结点
        AVLNode right = node.right;
        // leftOfRight 代表图中的可能存在的乙子树的根结点
        AVLNode leftOfRight = right.left;
        /*
        其中: m != null && right != null
        但是: parent 不保证 !null, leftOfRight 不保证 !null
         */

        right.parent = parent;  // 蓝色线的关系
        // 黑色线的关系
        if (parent == null) {
            // m 是 root
            root = right;
        } else {
            if (node == parent.left) {
                parent.left = right;
            } else {
                parent.right = right;
            }
        }

        right.left = node; // 黑色线的关系
        node.parent = right;   // 蓝色线的关系

        node.right = leftOfRight;
        if (leftOfRight != null) {
            leftOfRight.parent = node;
        }
    }

    private void rightRotate(AVLNode node) {
        AVLNode parent = node.parent;
        AVLNode left = node.left;
        AVLNode rightOfLeft = left.right;

        left.parent = parent;
        if (parent == null) {
            root = left;
        } else {
            if (node == parent.left) {
                parent.left = left;
            } else {
                parent.right = left;
            }
        }

        left.right = node;
        node.parent = left;

        node.left = rightOfLeft;
        if (rightOfLeft != null) {
            rightOfLeft.parent = node;
        }
    }

}

AVLTree的节点

// 不包含 value
// key 的类型也是 long
// 结点中需要多保存两个字段
// 1. 以该结点为根的子树的平衡因子 bf
// 2. 该结点的父结点 parent
public class AVLNode {
    public long key;

    public AVLNode left;
    public AVLNode right;

    // AVL 树中的特殊字段
    public int bf;
    public AVLNode parent;

    @Override
    public String toString() {
        return "AVLNode{" +
                "key=" + key +
                ", bf=" + bf +
                '}';
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值