二、二叉树的前世今生

为什么要有树

一百个数字,无序排列,我们要根据已知的某个数字a,找到a在这一百个数字中的位置(也就是下标),如何寻找?遍历。假设100个数字可以每次遍历,1万个可以每次遍历,100万个还可以么?再计算遍历的频率,不好好掌握,简单的遍历就可以把负责遍历的人给忙死。

这时候人们开始思考,怎么样可以快速定位呢?很简单,如果插入的时候有顺序,那么这样的遍历就变得非常简单。我们都知道1-100中间如果要找某个数字,我们肯定第一个判断的是50这个数值与要定位的数字a的大小对比(因为有序了,所以大小对比才有意义)。如果小于50,那么我们下一次会先判断25,如果大于50,那么我们会判断75……这就是常见的二分法,我们判断出来要找的数字小于50时,我们就不需要去判断50-100中间的这一堆数字,对比遍历,我们就相当于少了一半多工作量,一直循环下去,对比遍历,遍历的数据越多,效率越高。具体研究请自行百度 二分法 时间/空间复杂度,去得出结论。

编程中遇到这样的问题就有更多,因为查找的效率严重影响我们系统反应的时间。计算机中如何体现上文所述的二分法呢?聪明的人根据二分法的判断顺序,设计了一个有左子树,右子树的树形结构,命名为二叉树。二叉树必须有序,否则无序的二叉树,数据来了都不知道要放在什么地方

比如我们设计一个树,排序规则为,大于节点的放在左边,小于节点的放在右边

u=1251640940,4272012906&fm=173&s=49A43D724991F8CC4CDDC4DE0000C0B1&w=422&h=230&img.JPEG

得出这样一个树,有序,但这就是二叉树的最坏情况,不能做到高效查询,如果我们没有定义好一个最有意义的ROOT节点,那么很可能会出现这种情况,那么情况总是不能避免,到底如何定义一个最有意义的ROOT节点呢?于是,平衡左树与右树的平衡二叉树应运而生。(它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树)

二叉树旋转的实现 左旋/右旋

1) 右旋: 左边树结构深度 大于 右边树结构深度,且大于1时,进行右旋

u=35636183,3506846196&fm=173&s=C5B03D720F005C4110F545CE000070B1&w=640&h=292&img.JPEG

2) 左旋: 左边树结构深度 小于 右边树结构深度,且小于1时,进行左旋

u=3943120227,3713743074&fm=173&s=E130257207705C2352DC55CA0000E0B3&w=640&h=239&img.JPEG

将平衡二叉树完成之后,有效的数据排序之后,大致会得到一个类似下图的结果。

u=2204933443,1672249519&fm=173&s=48AC3C7219B7C8CE4EF878CA0000E0B1&w=640&h=446&img.JPEG

这样的情况下,我们进行1-7的数字判断,最快需要1次,最慢需要3次,而使用传统的遍历对比,最快要1次,最慢7次。数据量越大的情况下,这里的性能差距会越大。

平衡二叉树诞生,让所有人尝到了甜头,其实简单的说就是,就是降低了二叉树的时间复杂度,即从最顶端,到最底端的时间。那么二叉树的层数到底还能不能减?当然可以,于是,2-3树诞生。

2-3树每个节点保存1个或者两个的值。对于普通的2节点(2-node),他保存1个key和左右两个自己点。对应3节点(3-node),保存两个Key,2-3查找树的定义如下:

1) 要么为空,要么:

2) 对于2节点,该节点保存一个key及对应value,以及两个指向左右节点的节点,左节点也是一个2-3节点,所有的值都比key有效,有节点也是一个2-3节点,所有的值比key要大。

3)对于3节点,该节点保存两个key及对应value,以及三个指向左中右的节点。左节点也是一个2-3节点,所有的值均比两个key中的最小的key还要小;中间节点也是一个2-3节点,中间节点的key值在两个跟节点key值之间;右节点也是一个2-3节点,节点的所有key值比两个key中的最大的key还要大。

即类似这样的一个形状

u=3732344845,3003710703&fm=173&s=85B87D3293D449C20851D1D3000050B0&w=520&h=182&img.JPEG

这样的实现,如图中八个节点,在平衡二叉树中,需要深度为3的树结构,只需要两层就可以实现。但是对比平衡二叉树,大大增加了插入/删除/修改的难度,降低了查询的难度,利弊参半。

由于2-3树的复杂,人们考虑可不可以对2-3树和平衡二叉树的复杂度折中一下,于是出现了红黑树。

红黑树相当于一个2-3树的简单实现,简单演示一下2-3树如何转换为红黑树

2-3树

u=4120702356,3721901771&fm=173&s=C9AC3C7201DAD9C61C75E0CA0000C0B2&w=640&h=315&img.JPEG

红黑树

u=281965079,3420334914&fm=173&s=58A23C7251DBC9C206D0B5CE0000A0B1&w=640&h=318&img.JPEG

当然这个树并不满足真正的红黑树,这里只做一个2-3树转换红黑树的过程,简单说一下对比2-3树,为什么更为广泛应用的原因:

2-3查找树,这种数据结构在插入之后能够进行自平衡操作,降低了时间复杂度。但是2-3查找树实现起来比较困难,红黑树是2-3树的一种简单高效的实现,运用颜色标记来替代2-3树中比较难处理的3节点问题。

本文只是javashop小刘个人理解,简单入门,如果需要仔细学习,建议阅读《算法导论》,他自己还没来得及看,都是他本人的一些积累,他告诉小编我有空一定仔细阅读一遍。另外下一片重点说明在数据量更多,更大的情况下,二叉树无法完全胜任的情况下,b-树和b+树衍变。

转载于:https://my.oschina.net/u/3933814/blog/2243961

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值