Java 树结构的算法
   
    
    
    基本概念
   
    
    
    定义
   
    **树(Tree)**是n(n>=0)个节点的有限集。n=0时称为空树。在任意一颗非空树中:
    
    (1)有且仅有一个特定的称为根(Root)的节点;
    
    (2)当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1、T2、…、Tn,其中每一个集合本身又是一棵树,并且称为根的子树。
    
    此外,树的定义还需要强调以下两点:
    
    (3)n>0时根节点是唯一的,不可能存在多个根节点,数据结构中的树只能有一个根节点。
    
    (4)m>0时,子树的个数没有限制,但它们一定是互不相交的。
   
    
    
    节点的度
   
    
     定义:
     
      节点拥有的子树数目称为节点的
     
     度
    
    。例如:图3.2中标注了图3.1所示树的各个节点的度。
   
    
    
    节点关系
   
    节点子树的根节点为该节点的
    
     孩子节点
    
    。相应该节点称为孩子节点的
    
     双亲节点
    
    。图3.2中,A为B的双亲节点,B为A的孩子节点。
    
    同一个双亲节点的孩子节点之间互称
    
     兄弟节点
    
    。图3.2中,B与C互为兄弟节点,GHI互为兄弟节点,EF互为兄弟节点。
   
    
    
    节点层次
   
从根节点开始,根节点为第一层,根的孩子为第二层,以此类推。例如:图3.4表示了图3.1所示树的层次关系
    
   
    
    
    树的深度
   
树中节点的最大层次数称为树的深度或高度。
    
    
    二叉树
   
    
    
    定义
   
    
     二叉树
    
    是n(n>=0)个节点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树组成。
    
    图4.1展示了一棵一般二叉树
   
    
   
    
    
    二叉树特点
   
    由二叉树的定义,以及图中所示的二叉树的分析可以得出二叉树具有以下几个特点:
    
    (1)每个节点最多有两颗子树,所以二叉树中不存在度大于2的节点。
    
    (2)左子树和右子树是有顺序的,次序不能任意颠倒。
    
    (3)即使树中某节点只有一棵子树,也要区分它是左子树还是右子树。
   
    
    
    二叉树性质
   
    (1)在二叉树的第i层上最多有2i-1 个节点 。(i>=1)
    
    (2)二叉树中如果深度为k,那么最多有2k-1个节点。(k>=1)
    
    (3)n0=n2+1 n0表示度数为0的节点数,n2表示度数为2的节点数。
    
    (4)在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]是向下取整。
    
    (5)若对含 n 个节点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的节点有如下特性:
    
    (5)- 1,若 i=1,则该节点是二叉树的根,无双亲, 否则,编号为 [i/2] 的节点为其双亲节点;
    
    (5)- 2,若 2i>n,则该节点无左孩子, 否则,编号为 2i 的节点为其左孩子节点;
    
    (5)- 3,若 2i+1>n,则该节点无右孩子节点, 否则,编号为2i+1 的节点为其右孩子节点。
   
    
    
    斜树
   
所有的节点都只有左子树的二叉树叫左斜树。所有节点都是只有右子树的二叉树叫右斜树,这两者统称为斜树。
    
    
    满二叉树
   
在一棵二叉树中。如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
    满二叉树的特点有:
    
    (1)叶子只能出现在最下一层。出现在其它层就不可能达成平衡。
    
    (2)非叶子节点的度一定是2。
    
    (3)在同样深度的二叉树中,满二叉树的节点个数最多,叶子节点数最多。
   
    
    
    完全二叉树
   
    
     完全二叉树
    
    :对一颗具有n个节点的二叉树按层编号,如果编号为i(1<=i<=n)的节点与同样深度的满二叉树中编号为i的节点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。 图4.6为一棵完全二叉树
   
    
   
    
     完全二叉树特点
    
    :
    
    (1)叶子节点只能出现在最下层和次下层。
    
    (2)最下层的叶子节点集中在树的左部。
    
    (3)倒数第二层若存在叶子节点,一定在右部连续位置。
    
    (4)如果节点度为1,则该节点只有左孩子,即没有右子树。
    
    (5)同样节点数目的二叉树,完全二叉树深度最小。
   
    
    
    二叉树的存储结构
   
    
     (1)顺序存储
    
    
    二叉树的顺序存储结构就是使用一维数组存储二叉树中的节点,并且节点的存储位置,就是数组的下标索引
   
    
   
例如:所示的一棵完全二叉树采用顺序存储方式,表示:
    
   
当二叉树为完全二叉树时,节点数刚好填满数组。那么当二叉树不为完全二叉树时,采用顺序存储形式如何呢?
    
   
其中,未填充节点表示节点不存在。那么图4.7.2所示的二叉树的顺序存储结构如图4.7.3所示:
    
   
其中,∧表示数组中此位置没有存储节点。此时可以发现,顺序存储结构中已经出现了空间浪费的情况。
右斜树极端情况
    
   
采用顺序存储的方式是十分浪费空间的。因此,顺序存储一般适用于完全二叉树
    
     二叉链表
    
   
既然顺序存储不能满足二叉树的存储需求,那么考虑采用链式存储。由二叉树定义可知,二叉树的每个节点最多有两个孩子。因此,可以将节点数据结构定义为一个数据和两个指针域。表示方式如图所示
    
   
    
    
    二叉搜索树
   
    
    
    定义
   
二叉搜索树又称二叉查找树,亦称为二叉排序树。设x为二叉查找树中的一个节点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个节点,则key[y] <= key[x];如果y是x的右子树的一个节点,则key[y] >= key[x]。
     (1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值;
    
    (2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值;
    
    (3)左、右子树也分别为二叉搜索树;
   
    
   
不是一棵二叉搜索树
    
   
    
    
    节点结构
   
二叉树的节点结构通常包含三部分,其中有:左孩子的指针,右孩子指针以及数据域。节点的图示如下:
    
   
    
    
    创建二叉搜索树
   
    
    
    查找
   
    
     查找流程:
    
   
    (1)如果树是空的,则查找结束,无匹配。
    
    (2)如果被查找的值和节点的值相等,查找成功。
    
    (3)如果被查找的值小于节点的值,递归查找左子树,
    
    (4)如果被查找的值大于节点的值,递归查找右子树,
   
    
    
    插入
   
    
     插入流程
    
   
     (1)先检测该元素是否在树中已经存在。如果已经存在,则不进行插入;
    
    (2)若元素不存在,则进行查找过程,并将元素插入在查找结束的位置。
   
    
    
    删除
   
    
     删除节点为叶子节点
    
   
删除叶子节点的方式最为简单,只需查找到该节点,直接删除即可。
    
     删除的节点只有左子树
    
   
删除的节点若只有左子树,将节点的左子树替代该节点位置。
    
     删除的节点只有右子树
    
   
删除的节点若只有右子树,将节点的右子树替代该节点位置。
    
     删除的节点既有左子树又有右子树。
    
   
    若删除的节点既有左子树又有右子树,这种节点删除过程相对复杂。其流程如下:
    
    (1)遍历待删除节点的左子树,找到其左子树中的最大节点,即删除节点的前驱节点;
    
    (2)将最大节点代替被删除节点;
    
    (3)删除左子树中的最大节点;
    
    (4)左子树中待删除最大节点一定为叶子节点或者仅有左子树。按照之前情形删除即可。
   
注:同样可以使用删除节点的右子树中最小节点,即后继节点代替删除节点,此流程与使用前驱节点类似。
    
    
    前驱节点
   
节点val值小于该节点val值并且值最大的节点
    
    
    后继节点
   
节点val值大于该节点val值并且值最小的节点
    
    
    平衡二叉树
   
    
    
    平衡因子
   
**定义:**某节点的左子树与右子树的高度(深度)差即为该节点的平衡因子(BF,Balance Factor),平衡二叉树中不存在平衡因子大于1的节点。在一棵平衡二叉树中,节点的平衡因子只能取-1、1或者0。
平衡因子过大不在这范围之内会造成左旋和右旋,来形成自平衡二叉树(AVL)
左旋和右旋:
https://xiaozhuanlan.com/topic/2937850641
    
    
    
     2-3树
    
   
    前面讲到了二叉搜索树(BST)和二叉平衡树(AVL),二叉搜索树在最好的情况下搜索的时间复杂度为O(logn),但如果插入节点时,插入元素序列本身就是有序的,那么BST树就退化成一个线性表了,搜索的时间复杂度为O(n)。
    
    如果想要减少比较次数,就需要降低树的高度。在插入和删除节点时,要保证插入节点后不能使叶子节点之间的深度之差大于1,这样就能保证整棵树的深度最小,这就是AVL树解决BST搜索性能降低的策略。但由于每次插入或删除节点后,都可能会破坏AVL的平衡,而要动态保证AVL的平衡需要很多操作,这些操作会影响整个数据结构的性能,除非是在树的结构变化特别少的情形下,否则AVL树平衡带来的搜索性能提升有可能还不足为了平衡树所带来的性能损耗。
    
    因此,引入了2-3树来提升效率。2-3树本质也是一种平衡搜索树,但2-3树已经不是一棵二叉树了,因为2-3树允许存在3这种节点,3-节点中可以存放两个元素,并且可以有三个子节点。
   
    
     定义
    
   
    (1)2-3树要么为空要么具有以下性质:
    
    (2)对于2-节点,和普通的BST节点一样,有一个数据域和两个子节点指针,两个子节点要么为空,要么也是一个2-3树,当前节点的数据的值要大于左子树中所有节点的数据,要小于右子树中所有节点的数据。
    
    (3)对于3-节点,有两个数据域a和b和和三个子节点指针,左子树中所有的节点数据要小于a,中子树中所有节点数据要大于a而小于b,右子树中所有节点数据要大于b。
   
    
    
    性质
   
    (1)对于每一个结点有1或者2个关键码。
    
    (2)当节点有1个关键码的时,节点有2个子树。
    
    (3)当节点有2个关键码时,节点有3个子树。
    
    (4)所有叶子点都在树的同一层
   
增删改查:
http://www.360doc.com/content/19/0213/21/58006001_814757954.shtml
    
    
    结语
   
2-3 树作为一种平衡查找树,查询效率比普通的二叉排序树要稳定许多。但是2-3树需要维护两种不同类型的结点,查找和插入操作的实现需要大量的代码,而且它们所产生的额外开销可能会使算法比标准的二叉查找树更慢。
    
    
    
     2-3-4树
    
   
- https://xiaozhuanlan.com/topic/7128365094
 
ps:我没看出来这个和红黑树和二叉树有什么等价关系?
答:
    
    
    2-3-4树和红黑树的等价关系
   
如果一棵树满足红黑树,把红色节点收缩到其父节点,就变成了2-3-4树,所有红色节点都与其父节点构成3或4节点,其它节点为2节点。一颗红黑树对应唯一形态的2-3-4树,但是一颗2-3-4树可以对应多种形态的红黑树(主要是3节点可以对应两种不同的红黑树形态)。
    
   
    
    
    红黑树的特点总结
   
- 
搜索树用于查询
 - 
但是在自增长时,搜索树的查询效率降低,于是就有了平衡二叉树
 - 
平衡二叉树的查询效率很高,但是在增加和删除元素时,会进行重新的平衡,自旋,次数较多导致效率较低
 - 
红黑树 的定义:到叶子节点的高度可以最大N+N(黑树必须是N,另外一个红树可以是N),也就是红黑树可以不是完全的平衡二叉树。这样的效果是减少了自选、平衡次数,但是还是平衡二叉树的查询效率最高
 - 
B-树 特例是2- 3树 注意其 增加和删除元素的逻辑,每个树中的节点既保存索引还有卫星数据(真实数据)
所以在查询效率不稳定,前面找到了则就快,找不到就慢了,因为是2-3树相对可以减少IO次数
 - 
B+树 性质:每个节点中的个数决定了其子树的个数,所有的卫星数据都在叶子节点中,并且是用链表中进行连接。这样的查询稳定性较高,并且节点个数的限制,每个节点可以有更多的元素,IO次数也会减少
 
完全的平衡二叉树。这样的效果是减少了自选、平衡次数,但是还是平衡二叉树的查询效率最高
- 
B-树 特例是2- 3树 注意其 增加和删除元素的逻辑,每个树中的节点既保存索引还有卫星数据(真实数据)
所以在查询效率不稳定,前面找到了则就快,找不到就慢了,因为是2-3树相对可以减少IO次数
 - 
B+树 性质:每个节点中的个数决定了其子树的个数,所有的卫星数据都在叶子节点中,并且是用链表中进行连接。这样的查询稳定性较高,并且节点个数的限制,每个节点可以有更多的元素,IO次数也会减少