高阶数据结构

一、AVL树

1.AVL的定义和特征

特征:搜索树&&平衡树
搜索树:任取结点,其左孩子.key<其.key<右孩子.key,因此中序遍历是有序的,按照key值顺序大小排列
平衡树:结点左子树的高度和结点右子树的高度的高度差的绝对值不超过1
平衡因子:bf(node)=H(node.left)-H(node.right)

2.AVL的操作步骤

①查找

在这里插入图片描述
如果 key==current.key: 查找到了key,current就是包含了key的结点
如果 key<current.key: current=current.left
如果 key>current.key: current=current.right
如果current == null :key不在集合中

时间复杂度~O(树的高度) 即O(log(n))

②插入
1.按照普通搜索树的插入规则进行结点的插入
2.随着插入的完成,导致平衡因子出现的变化,所以要进行平衡因子的调节

BF(node)==0
BF(parent.parent) 不变
BF(parent)

  • if(node是parent.left) 则 H(parent.left)++ 即 BF(parent)++

  • else(node是parent.right) 则 H(parent.right)++ 即 BF(parent)–

失衡情况:
在这里插入图片描述

LL:对parent右旋,插入结束
LR:对node左旋,对parent右旋,插入结束
RR:对parent左旋,插入结束
RR:对node右旋,对parent左旋,插入结束

3.AVL树的插入过程正确性的证明

请添加图片描述

4.AVL树的实现

结点

public class AVLNode {
   
    public long key;
    public AVLNode left;
    public AVLNode right;
    //特殊字段
    public int bf;    //平衡因子
    public AVLNode parent;  //父结点

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

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 m) {
   
        // m 代表图中的 b 结点
        // parent 代表 b 结点可能存在的父亲
        AVLNode parent = m.parent;
        // right 代表图中的 a 结点
        AVLNode right = m.right;
        // leftOfRight 代表图中的可能存在的乙子树的根结点
        AVLNode leftOfRight = right.left;
        /*
        其中: m != null && right != null
        但是: parent 不保证 !null, leftOfRight 不保证 !null
         */

        right.parent = parent;  // 蓝色线的关系
        // 黑色线的关系
        if (parent == null) {
   
            
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值