红黑树与跳表

文章对比了红黑树和跳表的特性,指出红黑树适用于频繁的插入、删除操作,而跳表在区间查找上效率更高。Redis选择跳表作为有序集合的实现方式,除了效率考虑,还因为跳表实现更简单、可读性好,且可以通过调整索引来平衡效率和内存消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先分析一波红黑树吧。。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
根节点到任意一个叶子节点所经过的节点数量是相同的
在这里插入图片描述
在这里插入图片描述

  1. 每个节点或者是红色,或者是黑色(定义)
  2. 根节点一定是黑色的(对应2-3树的2节点和3节点)
  3. 空节点是黑色的
  4. 如果一个节点是红色的,那么它的孩子节点都是黑色的
  5. 根节点到任意一个叶子节点所经过的黑节点个数是一样的,即红黑树是一颗保持黑平衡的二叉树,不是平衡二叉树,但左右子树的黑色节点保持绝对的平衡,增删改查复杂度 O(logN),添加和删除操作比AVL树快
    在这里插入图片描述
    我们刚刚提到了很多平衡二叉查找树,现在我们就来看下,为什么在工程中大家都喜欢用红黑树这种平衡二叉查找树?我们前面提到Treap、Splay Tree,绝大部分情况下,它们操作的效率都很高,但是也无法避免极端情况下时间复杂度的退化。尽管这种情况出现的概率不大,但是对于单次操作时间非常敏感的场景来说,它们并不适用。AVL树是一种高度平衡的二叉树,所以查找的效率非常高,但是,有利就有弊,AVL树为了维持这种高度的平衡,就要付出更多的代价。每次插入、删除都要做调整,就比较复杂、耗时。所以,对于有频繁的插入、删除操作的数据集合,使用AVL树的代价就有点高了。红黑树只是做到了近似平衡,并不是严格的平衡,所以在维护平衡的成本上,要比AVL树要低。所以,红黑树的插入、删除、查找各种操作性能都比较稳定。对于工程应用来说,要面对各种异常情况,为了支撑这种工业级的应用,我们更倾向于这种性能稳定的平衡二叉查找树。
跳表和红黑树
Redis 为何选用跳表
  • 有序的单链表 O(N)
  • 提高查找效率 --》 对链表建立索引
  • 建立了多级索引,每层索引中,每个节点指向有两个指向,向右和向下
  • 每一层索引节点个数是下层节点个数的一半
  • 查询效率O(logN), 插入,删除也是
  • 通过随机函数维持平衡性,当往跳表中插入数据时,可以通过随机函数选择选择向哪些索引中添加节点,

Redis中的有序集合是通过跳表来实现的,严格点讲,其实还用到了散列表。如果你去查看Redis的开发手册,就会发现,Redis中的有序集合支持的核心操作主要有下面这几个:
插入一个数据;
删除一个数据;
查找一个数据;
按照区间查找数据(比如查找值在[100, 356]之间的数据);
迭代输出有序序列。
其中,插入、删除、查找以及迭代输出有序序列这几个操作,红黑树也可以完成,时间复杂度跟跳表是一样的。但是,按照区间来查找数据这个操作,红黑树的效率没有跳表高。
对于按照区间查找数据这个操作,跳表可以做到O(logn)的时间复杂度定位区间的起点,然后在原始链表中顺序往后遍历就可以了。这样做非常高效。
当然,Redis之所以用跳表来实现有序集合,还有其他原因,比如,跳表更容易代码实现。虽然跳表的实现也不简单,但比起红黑树来说还是好懂、好写多了,而简单就意味着可读性好,不容易出错。还有,跳表更加灵活,它可以通过改变索引构建策略,有效平衡执行效率和内存消耗。

B+树
  • 支持区间 (叶子节点连在一个链表上)
  • 减少磁盘IO,(降低高度);m叉树,m越大越好?:操作系统按页来读取(4KB)。如果读取的数据量超过一页,就会触发多次IO操作。因此,在选择m的时候,尽量让每个节点的大小等于一个页的大小在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值