JAVA 算法——树

1、二叉搜索树

    二叉搜索树需满足以下四个条件:

  1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  3. 任意节点的左、右子树也分别为二叉查找树;
  4. 没有键值相等的节点。

2、什么是伸展树(Splay Tree) 

假设想要对一个二叉查找树执行一系列的查找操作。为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。splay tree应运而生。splay tree是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。

3、AVL树

AVL树是一种最古老的平衡树,它的平衡条件是:每个节点的左子树和右子树的高度最多相差1。对于插入、删除等改变树高度的操作,会通过旋转使树满足平衡条件。假设删除采用的是懒惰删除(即不移除节点,只将节点标识为已删除),那么对于插入则会出现下面四种情况。假设M表示从叶子上溯到根的过程中出现的第一个不平衡点。
        1,对M的左儿子的左子树进行一次插入,简记左-左。
        2,对M的右儿子的右子树进行一次插入,简记右-右。
        3,对M的左儿子的右子树进行一次插入,简记左-右。
        4,对M的右儿子的左子树进行一次插入,简记右-左。
        上述四种情况,前两种可以使用单旋转进行解决,后两种要使用双旋转(即进行两次单旋转)。
        对于左-左:将M与M左儿子L进行旋转——将M变为L的右儿子,而L的右儿子变为M的左儿子。对于右-右也类似。
        对于左-右,将M与M的左儿子L与L的右儿子G进行旋转——先将G与L进行右-右旋转,再将G与M进行左-左旋转。

4、节点自平衡树(Size Balanced Tree,简称SBT)

Size Balanced Tree(简称SBT)是一种平衡二叉搜索树,它通过子树的大小s[t]来维持平衡性质。它支持很多动态操作,并且都能够在O(log n)的时间内完成。
为了下面方便讨论,
我们设
left [T] : 结点 T 的左儿子
right [T] : 结点 T 的右儿子
s [T] : 以T为根的子树的结点个数(大小))

SBT为什么能保持平衡?
  因为 对于SBT的每一个结点 t,有如下性质:
   性质(a) s[ right[t] ]≥s[ left [ left[ t ] ] ], s[ right [ left[t] ] ]
   性质(b) s[ left[t] ]≥s[right[ right[t] ] ], s[ left[ right[t] ] ]
即.每棵子树的大小不小于其兄弟的子树大小。(对于数组来实现树不熟悉的童鞋,请把s[ left [ left[ t ] ] ] 翻译为s[ t->left->left ] 同样的,s[ right [ left[t] ] ]翻译为s[ t->left->right ] )

5、Treap
Treap是用来排序(Sort)的一种数据结构(Data Structure)。reap是随机查找二叉平衡树。 Treap发音为tree+ Heap。顾名思义, Treap把 BST和 Heap结合了起来。它和 BST一样满足许多优美的性质,而引入堆目的就是为了维护平衡。 Treap在 BST的基础上,添加了一个修正值。在满足 BST性质的上,Treap节点的修正值还满足最小堆性质。最小堆性质可以被描述为每个子树根节点都小于等于其子节点。
(1) Treap的特点 :1.  Treap简明易懂。Treap只有两种调整方式,左旋和右旋。而且即使没有严密的数学证明和分析,Treap的构造方法啊,平衡原理也是不难理解的。只要能够理解 BST和堆的思想,理解 Treap当然不在话下。 
2.  Treap易于编写。Treap只需维护一个满足堆序的修正值,修正值一经生成无需修改。相
比较其他各种平衡树, Treap拥有最少的调整方式,仅仅两种相互对称的旋转。所以 Treap当之无愧是最易于编码调试的一种平衡树。 
3.  Treap稳定性佳。Treap的平衡性虽不如 AVL,红黑树, SBT等平衡树,但是 Treap也不会退化,可以保证期望 O(logN)的深度。Treap的稳定性取决于随机数发生器。 
4.  Treap具有严密的数学证明。Treap期望 O(logN)的深度,是有严密的数学证明的。但这不是介绍的重点,大多略去。 
5.  Treap具有良好的实践效果。各种实际应用中, Treap的稳定性表现得相当出色,没有因为任何的构造出的数据而退化。于是在信息学竞赛中,不少选手习惯于使用 Treap,均取得了不俗的表现。

一棵treap是一棵修改了结点顺序的二叉查找树,如图,显示一个例子,通常树内的每个结点x都有一个关键字值key[x],另外,还要为结点分配priority[x],它是一个独立选取的随机数。

假设所有的优先级是不同的,所有的关键字也是不同的。treap的结点排列成让关键字遵循二叉查找树性质,并且优先级(有的地方也叫修正值,是一个随机数)遵循最小堆顺序性质:

1.如果left是u的左孩子,则key[left] < key[u].
2.如果right是u的右孩子,则key[right] > key[u].

3.如果child是u的孩子,则priority[child] > priority[u].

4.如果priority[vi] < priority[vj].则vi相对于vj而言更接近根节点。

这两个性质的结合就是为什么这种树被称为“treap”的原因,因为它同时具有二叉查找树和堆的特征。(在关键字上它满足二叉排序树,在优先级上他满足小顶堆)。

用以下方式考虑treap会有帮助。假设插入关联关键字的结点x1,x2,...,xn到一棵treap内。结果的treap是将这些结点以它们的优先级(随机选取)的顺序插入一棵正常的二叉查找树形成的,亦即priority[xi] < priority[xj]表示xi在xj之前被插入。
在算法导论的12.4节中,其证明了随机构造的二叉查找树的期望高度为O(lgn),因而treap的期望高度亦是O(lgn)。

1.treap插入操作:
1.按照二叉树的插入方法,将结点插入到树中
2.根据堆的性质(我们这里为最小堆)和优先级的大小调整结点位置。

2.treap删除操作:
1.找到相应的结点
2.若该结点为叶子结点,则直接删除;
若该结点为只包含一个叶子结点的结点,则将其叶子结点赋值给它;

若该结点为其他情况下的节点,则进行相应的旋转,直到该结点为上述情况之一,然后进行删除。

Treap中的节点不仅满足BST的性质,还满足最小堆的性质。因此需要通过旋转来调整二叉树的结构,在维护Treap的旋转操作有两种:左旋和右旋,(注意:无论怎么旋转二叉查找树的性质是不能改变的)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值