有序表TreeMap/TreeSet底层实现:AVL树、傻逼树SBT、红黑树RBT、跳表SkipMap失衡类型

有序表TreeMap/TreeSet底层实现:AVL树、傻逼树SBT、红黑树RBT、跳表SkipMap失衡类型

提示:这段时间,讲有序表、跳表的底层数据结构,平衡搜索二叉树:AVL树,SB树,红黑树
基础知识:
【1】求二叉树中节点x的后继节点和前驱结点
【2】二叉树,二叉树的归先序遍历,中序遍历,后序遍历,递归和非递归实现
【3】平衡搜索二叉树BST底层的增删改查原理,左旋右旋的目的


题目

学习了解有序表treeMap,treeSet底层实现:傻逼树SBT(Size Balanced Tree)陈启峰平衡搜索二叉树

这个SBT可能面试官不让你手撕代码,但是你想要在互联网大厂长期干,混得不错,还得好好学这个知识
你得学习傻逼树SBT,AVL树,红黑树RBT,跳表,

尤其是SBT和跳表,这是你必须会的,面试场上可能直接让你手撕跳表的代码!
尤其是SBT和跳表,这是你必须会的,面试场上可能直接让你手撕跳表的代码!
尤其是SBT和跳表,这是你必须会的,面试场上可能直接让你手撕跳表的代码!


系统有序表TreeMap,TreeSet是刷题经常用的数据结构

有序表TreeMap经常我们联合堆结构,在互联网大厂的笔试题第一题用,用来解决贪心算法类的题目。

当年我学过哈希表HashMap,它不能排序,乱序的,但是操作复杂度为o(1)
今天要学:有序表TreeMap,它是一个自动给你排序key的数据结构,操作复杂度是o(log(n))

咱们玩几个案例:

    //系统有序表TreeMap,TreeSet是刷题经常用的数据结构

    public static void test(){
        TreeMap<Integer, Integer> treeMap = new TreeMap<>();
        treeMap.put(5, 2);
        treeMap.put(1, 2);
        treeMap.put(3, 2);
        treeMap.put(4, 2);
        treeMap.put(2, 2);
        //你会发现key是自动排序好的

        for(Integer i:treeMap.keySet()) System.out.print(i +" ");
    }

    public static void main(String[] args) {
        test();
    }
1 2 3 4 5 

添加或者更新操作:变key的value即可,put
得到key的value操作,get

treeMap.put(2, 3);
System.out.println(treeMap.get(2));
3

删除操作,删除key=2的

treeMap.remove(2);
for(Integer i:treeMap.keySet()) System.out.print(i +" ");
1 3 4 5 

首个key,尾部key

        System.out.println(treeMap.firstKey());
        System.out.println(treeMap.lastKey());
        1
        5

查询>=key的最近那个键:ceilingKey
查询<=key的最近那个键:floorKey

目前有序表是1 3 4 5

        System.out.println(treeMap.ceilingKey(2));
        System.out.println(treeMap.floorKey(7));
        3
        5

在这里插入图片描述
查询key是否存在?

        System.out.println(treeMap.containsKey(2));
        false

再说一下TreeSet实际上和哈希集HashSet类似,是没有value的key集合,只不过TreeSet的key也是有序的

你可以看到,TreeMap实际上就是一个key自动排序【可比较的】接口,以o(log(n))复杂度玩各种类似于哈希表的操作

为啥这个有序表的复杂度是o(log(n))???

因为有序表TreeSet和TreeMap底层是一个平衡搜索二叉树BST(balanced search tree),自然操作复杂度就是o(log(n))
关于平衡搜索二叉树的基础知识,看下面文章:
【3】平衡搜索二叉树BST底层的增删改查原理,左旋右旋的目的


有序表底层的几种数据结构:AVL树,SBT傻逼树,红黑树RBT,跳表SkipMap

今天我们先简洁这些数据结构的基本原理,后续文章我们会详尽地讲解SBT和跳表,因为跳表是大厂面试可能会让你手撕代码的地方,而傻逼树SBT是极其经典的一种树,但凡参加ACM极限编程比赛的大佬们,都用SBT干题
在这里插入图片描述

AVL树:

AVL树的名字来源于它的发明作者G.M. Adelson-Velsky 和 E.M. Landis
就像bfprt算法一样,它是根据五个发明这个算法的人的名字起的。

AVL树是最先发明的自平衡二叉搜索树(Self-Balancing Binary Search Tree,简称平衡二叉树)
它或者是一颗空树,
或者具有以下性质的二叉排序树:
它的左子树右子树的深度之差(平衡因子)的绝对值不超过1(<=1),
且它的左子树和右子树,各自也都是一颗平衡搜索二叉树
在这里插入图片描述

关于AVL树的根基知识,咱们前面讲过,如何判断一棵二叉树,是平衡搜索二叉树?你去学学。
求二叉树中,包含的最大二叉搜索子树的头节点是谁,它包含的节点数量是多少

SBT傻逼树:

傻逼树SBT是一个中国高中生发明的树
是针对AVL的缺陷做的改进,AVL树,但凡增删改查一个key,就非常容易扰动整个树,导致二叉树的平衡性被打破
你可能会经常要把AVL树拿过来想办法调平衡,麻烦死了……

作为高中生的陈启峰,在2006年在一个国际知名大赛中发明了节点大小平衡树(Size Balanced Tree,SBT),SBT如今在信息学领域广泛应用。

傻逼树SBT改进了AVL的平衡条件,不再是严格限制左右子的高度差<=1了
而是微微放宽了限制:让叔侄的节点数量势均力敌!
让x的兄弟节点【叔叔节点】,与x的左右子节点数量【叔叔的侄子节点】满足如下关系:
下图:
(1)叔叔b的节点数目>=任何以一个侄子的节点f/g数目
(2)叔叔c的节点数目>=任何以一个侄子的节点d/e数目
在这里插入图片描述
一旦违反(1)或(2)中任意一个条件,都不叫傻逼树SBT,需要调平衡。

但是总体来说,你增删改查,可能对二叉树的变动没那么大,扰动小,比AVL树调平操作的次数少多了,就没那么麻烦了,所以速度快一点,更好一些,因此SBT还挺经典的。

红黑树RBT:

红黑树的定义很特别,也复杂,这是所有二叉树中最复杂度的之一
必须满足下面几个条件才行:
(1)红黑树必须由红色或者黑色节点组成
(2)头结点和叶节点必须是黑节点
(3)红节点出现后,它的子必须是黑节点,黑节点的子可以是黑节点
(4)红黑红黑……这条最长的长链的长度N1必须=2×【2倍】黑黑黑黑……最短的短链长度N2

反正面试官是不可能考你红黑树的代码手撕的,否则它就是变态!
唯独华为牛逼的员工,要裁员时,谁能手撕红黑树,说明他真的很聪明,记忆力牛逼,他就不用被裁了
你能吗?
……
恐怖

跳表SkipMap

今天不说跳表,后续有文章会说,跳表是最重要的!要现场手撕代码的!

AVL树,SBT傻逼树,红黑树RBT不平衡需要调平,涉及左右旋

当AVL树,SBT傻逼树,红黑树RBT不平衡时,就需要左旋和右旋:
之前咱们就说过左旋和右旋的骚操作!
【3】平衡搜索二叉树BST底层的增删改查原理,左旋右旋的目的

那么不平衡的原因,是因为左子的问题?还是右子的问题?
因为不同的问题,导致的失衡状况,所需调平的方案是不同的
拿AVL树举例吧!

AVL树的左边高h1和右边高h2,高度差dh=|h1-h2|>1的话就是失衡了!
那么你得追问:究竟是h1那边高了,还是h2那边高了呢?
【这个AVL树可以作为了解的知识点,后面咱们要重点学傻逼树的失衡原因】

四种情况:
(1)由于x.l.l过高导致的,那就是LL型,即左子的左树引发的
(2)由于x.l.r过高导致的,那就是LR型,即左子的右树引发的
(2)由于x.r.l过高导致的,那就是RL型,即右子的左树引发的
(2)由于x.r.r过高导致的,那就是RR型,即右子的右树引发的
【所有树的失衡,大致就这四类,看看哪个孙子引发的问题,就这么命名】

LL型失衡及调平方案

(1)由于x.l.l过高导致的,那就是LL型,即左子的左树引发的
在这里插入图片描述
调平方案很简单:让a右旋即可
在这里插入图片描述
上图a右旋,导致a的节点数量或者高度可能变化,b的数量是原来a的数量,b的左右高度可能变化。

RR型失衡及调平方案

(4)由于x.r.r过高导致的,那就是RR型,即右子的右树引发的
与(1)相反的,让a左旋即可,因为右子右树引发的问题
下图左边就能判断
调平方案:让a左旋
在这里插入图片描述
调平之后,a和b左右高度可能都发生变化

LR型失衡及调平方案

(2)由于x.l.r过高导致的,那就是LR型,即左子的右树引发的
看下图这种情况就是,左树高7,右树高5,超过1的差,显然左树引发的,而且是左子的右树引发的,LR型
在这里插入图片描述
和RL类型相似的调平方案(下面说),都需要完成一个目标:即让x的肇事者孙子节点来替代x的位置
那必然调平比LL和RR多一步:先让孙子C替左子,再让孙子C替自己
本题LR引发的
1)先让a左旋,让孙子C接替左子
1)再让x右旋,让孙子C接替自己
目标已达成
在这里插入图片描述
只让左子左旋还不够的,中间那个图,仍然不平衡
还得让孙子c来接替x,这样才平衡了,右图看看
c从孙子节点一步一步上来接替自己,就完成了调平
你会发现:a,x,c仨节点的高度,或者节点数都变化了

RL型失衡及调平方案

(3)由于x.r.l过高导致的,那就是RL型,即右子的左树引发的
下图右树高7,左树高5,差大于1,右子的左树高度6,引发的问题,故RL型
在这里插入图片描述
和LR类型相似的调平方案(上面说),都需要完成一个目标:即让x的肇事者孙子节点来替代x的位置
那必然调平比LL和RR多一步:先让孙子C替右子b,再让孙子C替自己
本题RL引发的
1)先让b右旋,让孙子C接替右子
1)再让x左旋,让孙子C接替自己
目标已达成
在这里插入图片描述
上图b先右旋,让c上去,得到中间图,然后x左旋,让c上来,得到最右图,完成调平


总结

提示:重要经验:

1)有序表TreeMap,TreeSet底层实现是AVL树、傻逼树SBT、红黑树RBT、跳表SkipMap;当所有这些树失衡了之后,就需要调平,调平的四种方案:LL,RR,LR,RL操作都不一样,但是问题不大
2)傻逼树SBT和跳表是最重要的,系统有序表的实现往往是跳表实现的,有序表的各种操作类似于哈希表,但是操作复杂度是o(log(n))
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值