足交 telegram Java数据结构之均衡二叉树的旨趣与杀青

发布日期:2025-03-21 17:57    点击次数:150

足交 telegram Java数据结构之均衡二叉树的旨趣与杀青

均衡二叉树(AVL树),顾名想义,是一颗很“均衡”的树,它的均衡是相对于排序二叉树来说的。为了幸免极点情况下二叉搜索树节点分散不均匀,以致退化为链表,影响查找后果,咱们引入了均衡二叉树,即让树的结构看起来尽量“均匀”足交 telegram,傍边子树的节点数和层级尽量一样多。

本文详备先容了均衡二叉树的倡导和杀青旨趣,况兼提供了Java代码的完全杀青。

1 均衡二叉树的概述

为了幸免极点情况下二叉搜索树退化为链表,影响查找后果,咱们引入了均衡二叉树,即让树的结构看起来尽量“均匀”,傍边子树的节点数和层级尽量一样多。要想学习均衡二叉树况兼掌持它,必须要先掌持二叉排序树,如若对二叉搜索树还不太显著的,包括为什么二叉排序树可能退化为链表,不错望望这篇著述:数据结构—二叉排序树的旨趣以及Java代码的完全杀青。

均衡二叉树,又称AVL树,指的是左子树上的所有节点的值皆比根节点的值小,而右子树上的所有节点的值皆比根节点的值大,且左子树与右子树的高度差最大为1。因此,均衡二叉树知足所有二叉排序(搜索)树的性质,是在二叉排序树的基础上发展而来的。至于AVL,则是取自两个发明均衡二叉树的俄罗斯科学家的名字:G. M. Adelson-Velsky和E. M. Landis。

总的来说均衡二叉树具有如下性质:

它一定是一棵二叉排序树;它是一棵空树或它的傍边两个子树的高度差的十足值不逾越1,况兼傍边两个子树皆是一棵均衡二叉树,递归界说。

均衡因子BF(Balance Factor): 咱们将二叉树上节点的左子树深度减去右子树深度的值称为均衡因子,那么均衡二叉树上所有节点的均衡因子只能能是-1、0和1。只消二叉树上有一个节点的均衡因子的十足值大于1,则该二叉树即是不屈衡的。

上图中,图一是均衡二叉树,图二的59比58大,却是58的左子树,这是不合适二叉排序树的界说的,图二不是均衡二叉树。图3不是均衡二叉树的原因就在于,节点58的左子树高度为3,而右子树为空,二者差大于了十足值1,因此它也不是均衡的。而经过恰当的调养后的图4,它就合适了界说,因此它是均衡二叉树。

最小不屈衡子树: 距离插入、删除节点最近的,且均衡因子的十足值大于1的节点为根的子树,咱们称为最小不屈衡子树。下图中当新插入节点37时,距离它最近的均衡因子十足值逾越1的节点是58(即它的左子树高度3减去右子树高度1),是以从58运转以下的子树为最小不屈衡子树。

2 均衡二叉树的杀青旨趣

均衡二叉树杀青旨趣的中枢即是:由于在插入、删除节点以后,唯有那些从插入点到根节点的旅途上的节点的均衡可能被改造,因为唯有这些节点的子树可能发生变化。因此,咱们需要沿着这条旅途上行到根并更新均衡信息,尝试找出最小不屈衡树。在保持二叉排序树特点的前提下,调养最小不屈衡子树中根节点和子结点之间的干系,进行相应的旋转(rotation),使之成为新的均衡子树。

先来望望插入的重均衡,因为到背面咱们会发现插入和删除进行的重均衡操作基本是一致的。

咱们把需要进行均衡(均衡因子十足值大于1)的节点称为x,由于即兴节点最多有两个犬子,因此出现高度不屈衡就需要x点的两棵子树的高度差2,而这种不屈衡只能能出现鄙人面四种情况中:

在节点X的左孩子节点的左子树中插入元素,简称LL在节点X的左孩子节点的右子树中插入元素,简称LR在节点X的右孩子节点的左子树中插入元素,简称RL在节点X的右孩子节点的右子树中插入元素,简称RR

其中第1种情况和第4种情况是对称的,被称为发生“外边”的情况,不错通过单旋转来管制,而第2种情况和第3种情况是对称的,被称为发生在“内边”的情况,需要双旋转来管制。

案例:对数组中的元素{3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9}限定插入并建立一个均衡二叉树。以这个案例为例,来莳植上头4个问题的通用管制目的和单旋转和双旋转的倡导。

2.1 单旋转

最初是添加前两个元素“3、2”的本事,不错正常的构建均衡二叉树,到了第3个数“1”时,发现此时根节点“3”的均衡因子变成了2,此时整棵树皆成了最小不屈衡子树,因此需要调养结构。

上图中的情况情况合适要求1——LL,因此所袭取单旋转来重均衡。此时,咱们需要右旋(顺时针旋转)。旋转的标的内容上即是为了裁减深度,保持均衡。

节点3经过右旋后,节点2变成了根节点,节点3变成了2的右子树,此时树节点1的深度裁减了一级,整颗树从新回到了均衡。咱们把通过一次旋转即可建立均衡的操作叫作念单旋转。

均衡因子BF十足值大于1的节点X称为失衡点,建立一棵被苟且的AVL树时,找到失衡点是很蹙迫的,查找失衡点即是再行插入、删除的节点的位置朝上回溯至根节点的历程。

然后咱们再加多节点4,均衡因子莫得超出放肆畛域。加多节点5时,节点3的BF值为-2,讲解又要旋转了。

上图中的情况情况合适要求4——RR,需要袭取单旋转来重均衡。此时,咱们需要左旋(逆时针旋转)。

左旋之后,如上图右,树的深度裁减了一级,此时整棵树又达到了均衡气象。不息,加多节点6时,发现根节点2的BF值变成了-2,是以咱们对根节点进行了左旋。

左旋的终端使得节点2成为节点4的左孩子,正本处于2和4之间的节点3是4的左子树,由于旋转后需要知足二叉排序树特点,因此它成了节点2的右子树,因为该子树的每一个关节字皆在2-4之间,因此这个变换是确立的。

目下咱们来尝试追想起程生情况1和4时的通用解法。

最初,情况1和4不错索要出一个通用模子:

模子中,左边如若要发生不屈衡的情况1,那么左子树1的深度详情比右子树1的深度深2层;右边如若要发生不屈衡的情况4,那么左子树1的深度详情比右子树1的深度浅2层。

针对上头情况1和情况4,咱们分手使用右旋和左旋,来裁减大约升高这两颗子树的深度:

如上图,情况1右旋之后,k2成为根节点,k1成为k2的右子节点,k2的右子树2成为k1的左子树;情况4左旋之后,k2成为根节点,k1成为k2的左子节点,k2的左子树2成为k1的右子树。树从新达到了均衡气象,这即是管制情况1和情况4的通解,况兼咱们不错发现它们是对称的。

底下加多节点7,这导致节点5的BF变成了-2,且合适情况4,需要左旋,字据上头的通解,袭取底下的左旋递次让树从新成为均衡二叉树:

2.2 双旋转

上头的单旋转对于情况2和3是没灵验的,因为此时树结构太深,单旋转并不会减低它的深度。此时需要使用双旋转。

当加多节点16时,结构无变化,再加多节点15,此时节点7的BF变成了-2。此时合适情况3:在节点X的右孩子节点的左子树中插入元素,简称RL。如下图:

此时毛糙的左旋无法管制问题:节点15成了16的右孩子,这是不合适二叉排序树的特点的,此时不可毛糙的左旋。如下图:

对于这种情况,咱们对于关节节点7、16、15先建立一个更平方的模子:

其中7-k1、16-k2、15-k3,况兼节点7完全还不错领有左子树,节点16不错领有右子树,而节点15则不错领有傍边子树。

要想发生上头k1的BF为-2的情况,需要左子树2或右子树2其中一颗子树的深度比左子树1深两层,大约他们皆是空子树,可是咱们不知谈是具体是什么情况,不外这不谬误,在这里咱们要求出一个对这个问题通解!

此时为了均衡高度,咱们不可将k1行为根节点了,可是左旋——把k2行为根节点也不可管制问题(上头一经阐明了),唯独的给与即是:将k3行为新的根节点,况兼先使得k2右旋成为k3的右子树,然后k1左旋成为k3的左子树,况兼左子树2成为k1的右子树,右子树2成为k2的左子树,这是完全确立的,这即是情况3的通解。 最终,右-左双旋终端如下:

咱们不错看到,不管是具体发生了什么情况(左子树2或右子树2其中一颗子树的深度比左子树1深两层,大约他们皆是空子树),左-右双旋调度为上右图的时事之后,左子树2或右子树2皆会被削减一层深度,而左子树1会被加多一层深度,这棵树长久皆是一颗均衡二叉树。

内容上,右-左双旋,分开旋转的历程模子如下:

回到案例,案例中左子树2、右子树2、左子树1、右子树1皆是空树,使用右-左双旋之后,树结构如下图,该树得以从新均衡:

接着插入14,情况与刚才肖似,节点6的BF是-2,此时合适RL的情况(在节点6的右孩子节点15的左子树7中插入元素),如下图左,此时不息右-左双旋后,整棵树又回到了均衡气象,如下图右:

不息插入13,此时根节点4的BF变成了-2,合适情况4,此时使用一次单左片霎可管制问题:

不息插入12之后,朝上回溯到节点14时,发现节点14的BF为2,此时合适情况1,需要右旋归附均衡:

不息插入11之后,朝上回溯到节点15时,发现节点15的BF为2,此时合适情况1,需要右旋归附均衡:

不息插入10之后,朝上回溯到节点12时,发现节点12的BF为2,此时合适情况1,需要右旋归附均衡:

插入8之后,朝上回溯到根节点也莫得发现最小不屈衡树,因此不需要旋转。终末插入9之后,咱们发现出现了情况2,此时咱们多情况1和情况4对称的告诫,当然也知谈需要右-左双旋的的对称操作——左-右双旋来从新均衡。

先来看左-右双旋模子:

它和右-左双旋模子即是对称操作,将k3行为新的根节点,况兼先使得k2左旋成为k3的左子树,然后k1右旋成为k3的右子树,况兼左子树2成为k2的右子树,右子树2成为k1的左子树,这是完全确立的,这即是情况2的通解。

左-右双旋之后,从新变成了均衡二叉树:

内容上,左-右双旋,分开旋转的历程模子如下:

节点添加收场,最终变成了一颗均衡二叉树:

2.3 追想

插入节点的不屈衡的情况唯有四种:

在节点X的左孩子节点的左子树中插入元素,简称LL在节点X的左孩子节点的右子树中插入元素,简称LR在节点X的右孩子节点的左子树中插入元素,简称RL在节点X的右孩子节点的右子树中插入元素,简称RR

其中1袭取单右旋、4袭取单左片霎可管制问题。2和3比较复杂,2需要袭取左-右双旋、3需要袭取右-左双旋。

1和4、2和3是对称的情况,目下笼统起来看,所谓的旋转似乎也不那么复杂,况兼咱们一经求出了这几种问题的通解,该通解对于节点的删除是不异适用的,无须再探究多样稀奇情况,尽头毛糙,底下来望望具体的代码杀青!

3 均衡二叉树的构建

3.1 类架构

最初节点对象如故需要一个数据域和两个援用域,比拟于二叉排序树,还要多一个节点高度的字段,这么毛糙计较均衡因子,况兼提供复返节点高度的递次。 另外还需要一个比较器的援用,因为需要对元素进行排序,当然需要比较元素的大小,如若外部传递了比较器,那么就使用用户指定的比较器进行比较,不然,数据类型E必须是Comparable接口的子类,不然因为不可比较而报错。

另外,还需要提供中序遍历的递次,该遍历递次对于二叉排序树的终端将会限定展示。

男同porn

3.2 查找的递次

均衡二叉树即是一颗二叉排序树,其查找递次不错复用二叉排序树的查找递次,很毛糙:

若根节点的关节字值等于查找的关节字,生效,复返true;不然,若小于根节点的关节字值,递归查左子树;若大于根节点的关节字值,递归查右子树;最终查找到叶子节点如故没稀有据,那么查找失败,则复返false

3.3 检讨是否均衡的递次

很毛糙,只需要递归的稽查所有节点,判断是否存在的节点的傍边子节点高度差十足值是否大于1的情况就能判断了,如若存在,那么复返false示意不是均衡二叉树,不存在就复返true示意是均衡二叉树。

3.4 插入的递次

均衡二叉树和二叉排序树的最大区别即是在插入和删除的本事了。咱们一经斟酌过插入之后的4种出现均衡问题的稀奇情况,这里不再赘述,底下看代码具体奈何杀青:

3.4.1 测试

在insert之后打上断点,Debug,不错看到avlTree的数据结构和在杀青旨趣中最终的结构是一致的。

3.5 查找最大值和最小值

很毛糙,最左边的节点一定是最小的,最右边的节点一定是最大的。因此查找最小的节点只需要向左递归查找,查找最大的节点只需要向右递归查找。

3.6 删除的递次

均衡二叉树节点的删除不异可能导致产生不屈衡的气象,因此不异在二叉排序树的删除代码的基础上,删除元素之后需要在删除节点之上进行回溯直到根节点,尝试找出最小不屈衡树来进行重均衡。其均衡的递次是和插入的本事是一样的。

3.6.1 测试

针对上头插入的均衡二叉树进行删除:

在进行上头的一系列删除之后,树结构会变成如下时事:

4 均衡二叉树的追想

均衡二叉树是基于二叉排序树的,可是由于其必须保持均衡的特点,因此其编码难度比二叉排序树的编码难度更高,不外如若咱们搞懂了其旋转的旨趣,那么杀青起来如故比较毛糙的。

如若咱们需要查找的汇集自己莫得限定,在频繁查找的同期也需要通常的插入和删除操作,彰着咱们需要构建一棵二叉排序树,可是不屈衡的二叉排序树,极点情况下可能退化为链表,查找后果黑白常低的,因此咱们需要在构建时,就让这棵二叉排序树是动态的调度为均衡二叉树,此时咱们的查找时辰复杂度就为O(logn),而插入和删除也为O(logn)。这彰着是比较假想的一种动态查找表算法。

本文先容了均衡二叉树的旨趣以及Java代码的完全杀青,要想搞懂均衡二叉树需要先搞懂二叉排序树:二叉排序树的详解以及Java代码的完全杀青。而搞懂均衡二叉树又是搞懂红黑树的基础,后续著述咱们将会先容红黑树的倡导以及Java代码的完全杀青!

以上即是Java数据结构之均衡二叉树的旨趣与杀青的详备内容足交 telegram,更多对于Java均衡二叉树的贵寓请体恤剧本之家其它有关著述!



 



    Powered by VR视角 @2013-2022 RSS地图 HTML地图

    Copyright Powered by站群 © 2013-2024