Abstract Self-Balancing Binary Search Tree_sb树是谁发明的

本文介绍了二叉搜索树的原理,重点讨论了自平衡二叉搜索树如AVL树、红黑树和SBT等,强调了它们在保持平衡和优化操作时间复杂度上的重要性,以及左旋和右旋等基本操作。文中提到了在线学习资源和系统化学习的重要性。
摘要由CSDN通过智能技术生成

二叉搜索树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
具体介绍和实现:https://blog.csdn.net/hebtu666/article/details/81741034

我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度(O(log2n))同时也由此而决定。但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,

此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度

概念引入

Abstract Self-Balancing Binary Search Tree:自平衡二叉搜索树

顾名思义:它在面对任意节点插入和删除时自动保持其高度

常用算法有红黑树、AVL、Treap、伸展树、SB树等。在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在O(log(n)),大大降低了操作的时间复杂度。这些结构为可变有序列表提供了有效的实现,并且可以用于其他抽象数据结构,例如关联数组优先级队列集合

对于这些结构,他们都有自己的平衡性,比如:

AVL树

具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

根据定义可知,这是根据深度最严苛的标准了,左右子树高度不能差的超过1.

具体介绍和实现:https://blog.csdn.net/hebtu666/article/details/85047648

红黑树

特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

根据定义,确保没有一条路径会比其他路径长出2倍。

size balance tree

Size Balanced Tree(简称SBT)是一自平衡二叉查找树,是在计算机科学中用到的一种数据结构。它是由中国广东中山纪念中学的陈启峰发明的。陈启峰于2006年底完成论文《Size Balanced Tree》,并在2007年的全国青少年信息学奥林匹克竞赛冬令营中发表。由于SBT的拼写很容易找到中文谐音,它常被中国的信息学竞赛选手和ACM/ICPC选手们戏称为“傻B树”、“Super BT”等。相比红黑树、AVL树等自平衡二叉查找树,SBT更易于实现。据陈启峰在论文中称,SBT是“目前为止速度最快的高级二叉搜索树”。SBT能在O(log n)的时间内完成所有二叉搜索树(BST)的相关操作,而与普通二叉搜索树相比,SBT仅仅加入了简洁的核心操作Maintain。由于SBT赖以保持平衡的是size域而不是其他“无用”的域,它可以很方便地实现动态顺序统计中的selectrank操作。

对于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] ] ]
即.每棵子树的大小不小于其兄弟的子树大小。

伸展树

伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。它由Daniel Sleator和Robert Tarjan创造。它的优势在于不需要记录用于平衡树的冗余信息。在伸展树上的一般操作都基于伸展操作。

Treap

Treap是一棵二叉排序树,它的左子树和右子树分别是一个Treap,和一般的二叉排序树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉排序树的同时,还满足的性质(在这里我们假设节点的优先级大于该节点的孩子的优先级)。但是这里要注意的是Treap二叉堆有一点不同,就是二叉堆必须是完全二叉树,而Treap并不一定是。

对比可以发现,AVL树对平衡性的要求比较严苛,每插入一个节点就很大概率面临调整。

而红黑树对平衡性的要求没有那么严苛。可能是多次插入攒够了一下调整。。。

把每一个树的细节都扣清楚是一件挺无聊的事。。虽然据说红黑树都成了面试必问内容,但是实在是不想深究那些细节,这些树的基本操作也无非是那么两种:左旋,右旋。这些树的所有操作和情况,都是这两种动作的组合罢了。

所以本文先介绍这两种基本操作,等以后有时间(可能到找工作时),再把红黑树等结构的细节补上。

最简单的旋转

最简单的例子:

这棵树,左子树深度为2,右子树深度为0,所以,根据AVL树或者红黑树的标准,它都不平衡。。

那怎么办?转过来:

是不是就平衡了?

这就是我们的顺时针旋转,又叫,右旋,因为是以2为轴,把1转下来了。

左旋同理。

带子树旋转

问题是,真正转起来可没有这么简单:

这才是一颗搜索树的样子啊

ABCD都代表是一颗子树。我们这三个点转了可不能不管这些子树啊对不对。

好,我们想想这些子树怎么办。

首先,AB子树没有关系,放在原地即可。

D作为3的右子树,也可以不动,那剩下一个位置,会不会就是放C子树呢?

我们想想能否这样做。

原来:

1)C作为2的右子树,内任何元素都比2大。

2)C作为3左子树的一部分,内任何元素都比3小。

转之后:

1)C作为2的右子树的一部分,内任何元素都比2大。

2)C作为3左子树,内任何元素都比3小。

所以,C子树可以作为3的左子树,没有问题。

这样,我们的操作就介绍完了。

这种基本的变换达到了看似把树变的平衡的效果。

左右旋转类似

代码实现

对于Abstract BinarySearchTree类,上面网址已经给出了思路和c++代码实现,把java再贴出来也挺无趣的,所以希望大家能自己实现。

抽象自平衡二叉搜索树(AbstractSelfBalancingBinarySearchTree)的所有操作都是建立在二叉搜索树(BinarySearchTree )操作的基础上来进行的。

各种自平衡二叉搜索树(AVL、红黑树等)的操作也是由Abstract自平衡二叉搜索树的基本操作:左旋、右旋构成。这个文章只写了左旋右旋基本操作,供以后各种selfBalancingBinarySearchTree使用。

public abstract class AbstractSelfBalancingBinarySearchTree extends AbstractBinarySearchTree {
    protected Node rotateRight(Node node) {
        Node temp = node.left;//节点2
        temp.parent = node.parent;
        //节点3的父(旋转后节点2的父)
        node.left = temp.right;
        //节点3接收节点2的右子树
        if (node.left != null) {
            node.left.parent = node;
        }

        temp.right = node;
        //节点3变为节点2的右孩子
        node.parent = temp;

        //原来节点3的父(若存在),孩子变为节点2
        if (temp.parent != null) {
            if (node == temp.parent.left) {
                temp.parent.left = temp;
            } else {
                temp.parent.right = temp;
            }
        } else {
            root = temp;
        }
        return temp;
    }

    protected Node rotateLeft(Node node) {
        Node temp = node.right;
        temp.parent = node.parent;
        node.right = temp.left;
        if (node.right != null) {
            node.right.parent = node;
        }
        temp.left = node;
        node.parent = temp;
        if (temp.parent != null) {
            if (node == temp.parent.left) {
                temp.parent.left = temp;
            } else {
                temp.parent.right = temp;
            }
        } else {
            root = temp;
        }
        
        return temp;
    }
}

现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。

分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值