平衡树


最近在看红黑树,但是看了《算法导论》后,知其然,而不知其所以然。后来发现Knuth的高徒Robert Sedgewick是红黑树的发明人,于是就看他的著作《算法:C++实现》,同时也参考了网上的博客。特此记录。

前言

标准BST算法的最坏情况容易发生,需要解决方案。
周期性再平衡性能差,使得我们难以利用全局重新平衡来保障动态BST的快速性能。

解决方案:

  • 随机化
    向算法本身引入随机决策
  • 分期化
    每次都做额外的工作,以求避免稍后更多的的工作
  • 最优化
    为每个操作提供性能保障

随机化BST

新节点插入BST的方法有两种:

  • 根插入方法(向适当子树的根出入新数据项,然后通过旋转把它带到主干树的根)
  • 标准插入方法(将新节点作为叶节点插入)

新节点应该以概率 1 / ( N + 1 ) 1/(N+1) 1/(N+1)出现在树根,因此用这个概率做出进行根插入的随机决定,否则进行标准插入方法。

优点:

  • 随机化算法允许我们撤除对于插入操作,数据项以他们的关键字的随机排序出现这一假设。
  • 一棵随机化BST的构造开销大于平均水平 α \alpha α倍的概率小于 e − α e^{-\alpha} eα

缺点:

  • 每次插入期间在每个节点生成随机数的开销。
  • 需要每个节点记录该节点子树的节点数量

发散BST

修改根插入方法 如果把节点从作为树根的孙子之一的一个位置带到树顶部的两个旋转操作的旋转方向想同,那么直接在树根执行两次旋转操作。
优点:

  • 发散操作消除了最坏情况下的二次水平性能,而这正是标准BST的主要缺陷。
  • 在一棵 N N N节点的发散BST中执行 M M M个插入或者搜索操作构成的任意序列,所需要的比较次数是 O ( N + M ) lg ⁡ ( N + M ) ) O(N+M)\lg(N+M)) O(N+M)lg(N+M)) 这是分期化的性能保障: 我们保障的不是每种操作的高效执行,而是所有执行操作的平均开销是高效的。
  • 利用发散插入一个节点时,不仅将该节点带到了树根,而且使得(在搜索路径上)遇到的其他节点距离树根更近。

自上而下2-3-4树

随机化BST树和发散BST提供了良好的性能保障,但依然存在可能:一个特定搜索操作需要线性的时间。
平衡2-3-4搜索树是一棵2-3-4树搜索树,其中所有指向空树的链接和树根的距离都相同。其之所以重要的主要原因是:在每种情况中,我们都可以进行插入并仍能在树里保持完美平衡状态

为了消除回溯过程,在插入操作过程中可以采取预分裂的操作,即在插入的搜索路径中,遇到4节点就分裂(分裂后形成的根节点的key要上移,与父节点中的key合并)这样可以保证找到需要插入节点时可以直接插入(即该节点一定不是4节点)

与从上而下生长的标准BST不同,这些书被称为自下而上2-3-4树,因为四节点在自上而下的过程中分裂。

红黑树

自上而下2-3-4插入算法容易理解,但直接实现非常麻烦。红黑树的基本意念是把2-3-4树表示为标准BST,但每个节点加入额外的一位信息,以表示:把由三节点和四节点构成的小型二叉树绑合起来的红链接,以及绑合2-3-4树的黑链接。

每个节点都被一个链接所指向,所以对链接染色相当于对节点染色。

红黑树由两个核心性质:

  1. 对BST的标准搜索方法无须修改即可运作(简单搜索方法)
  2. 直接对应与2-3-4树。(简单的插入-平衡方法)

搜索方法不检查节点颜色,所以平衡机制不会令基本的搜索处理所需时间增加额外开销。

对比着红黑树与其所相应的2-3-4树,很容易明白红黑树的处理逻辑

N N N个节点的红黑树中的一次搜索需要少于 2 lg ⁡ + 2 2\lg+2 2lg+2次比较操作。

跳跃表

跳跃表是一个有序链表,其中每个节点包含有不定数量的链接,节点中的第 i i i个链接构成的单向链表跳过含有少于 i i i个链接的节点。

跳跃表的核心数据结构是平衡树的另外一种表示方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值