2-3树:满足二分搜索树的基本性质,节点可以存放一个元素或者两个元素。即每个节点有2个或者3个孩子。2-3树是一颗绝对平衡的树,左右子树的高度一定是相等的。
主要学习的几个树结构:二分搜索树(有可能退化成链表)、堆(完全二叉树)、线段树(数据分布在最后两层)、Trie、并查集、二叉平衡树(左右子树的高度差不能超过1)。
2-3树插入如何维持绝对的平衡?
添加节点,永远不会添加到空的位置,需要和我们最后找到的叶子节点做融合。
如果插入之后形成3节点,则什么都不需要做。
如果插入之后变成4节点,则需要进行分裂,若此时就是根节点则就结束。
如果插入之后变成4节点,其父亲节点是2节点,需要先分裂,再和父亲节点进行融合。
如果插入之后变成4节点,其父亲节点是3节点,需要先分裂再融合,融合之后其父亲节点变成了4节点,因此需要再进行分裂。
红黑树和2-3树的等价性
b和c之间用红色标识,表示b和c在之前的2-3树中是融合在一起的。
对于边来说是没有相应的类来表示的,那我们如何来表示特殊颜色的边呢?每一个节点只有一个父亲节点,也就是每个节点和父亲相连的只有一根边,可以把这条边的信息存放在节点上,如把这个节点变成红色。这个节点是红色就表示此节点和父亲节点在原来的2-3树上是融合的。
2-3树和红黑树的转化
红黑树是保持“黑平衡”的二叉树,严格来说,不是平衡二叉树,也就是说在红黑树中左右子树的高度有可能大于1,最大高度是2logN(每一个节点都是3节点)。
- 每一个节点都是黑色或者红色的
- 根节点是黑色的
- 每一个叶子节点(最后的空节点)是黑色的
- 如果一个节点是红色的,那么它的孩子节点都是黑色的
- 从任意一个节点到叶子节点,经过的黑色节点数量 是一样的(2-3树绝对平衡的,所有叶子节点都在最后一层,其深度是一致的。2-3树转成红黑树的时候,每一个节点都会有一个黑色的节点)
红黑树和AVL树
对于红黑树和AVL树而言:由于红黑树的最大高度比AVL树高,因此在查询的时候没有AVL树快;但是在添加和删除元素的时候,AVL要遵循严格的定义,其速度会比红黑树慢。
红黑树和AVL的区别:
红黑树是用非严格的平衡来换取旋转次数的降低,任何不平衡都会在三次旋转之内解决。而AVL树是严格的平衡,因此在增加或者删除节点的时候,旋转次数比红黑树多。
红黑树和AVL的使用场景区别:
应用操作性能主要集中在查询search操作的话,那就应该选择AVL。
应用操作性能主要集中delete和insert 的话还是选择红黑树更加具有优势。
红黑树添加元素
对于2-3树来说,每次往2-3树种插入元素都是融合到叶子节点上。对红黑树来说,每次添加的时候都添加红色节点,就是表示了2-3树的融合。添加了之后,有可能会破坏红黑树的基本性质,之后再进行相应的调整。
1.保持根节点是黑色的
刚开始添加元素、4节点进行分裂的时候需要保持根节点是黑色的。
2.左旋转
将当前节点的右孩子的左孩子指向自己。
左旋转等价为:2-3树中,将一个元素放入2节点,成为3节点的过程。
主要目的是,保证在左旋转后,保持3节点转为红黑树的定义,并不能保证红黑树的性质 。
插入42。
3.颜色翻转
2-3树中,将一个元素放入3节点,成为4节点,然后进行分裂和融合的过程。插入的元素是当前节点中的最大值。
插入66。
由于37和66是2节点,因此变成黑色,而42需要和父亲节点去融合,变成红色。
4.右旋转
将当前节点的左孩子的右孩子指向自己。
2-3树中,将一个元素放入3节点,成为4节点,然后进行分裂的过程。
插入的元素是当前节点中的最小值。
插入12。
右旋转操作完成之后,其4节点还处于融合阶段,需要进行分裂,用到颜色翻转的过程。
5. 左旋转–右旋转–颜色翻转
插入40。
为什么有了红黑树还需要B树呢?
当数据量大了之后,需要把数据存储在硬盘上,有需要就时候从磁盘中调取数据到内存中进行处理,因此需要I/O操作。一般一次I/O操作取出一个节点,红黑树高度很高,因此I/O次数更多。而B树是多叉树,其高度会大大降低,I/O次数就会大大减少。而对于B+树,其内节点无数据域,每个节点可以存储更多的关键字,导致高度进一步下降,I/O操作更友好。
此外,无论是B树,还是B+树、B树,由于根或者树的上面几层被反复查询,所以树上层几块的数据可以存在内存中。换言之,B树、B+树、B树的根结点和部分顶层数据存在内存中,大部分下层数据存在磁盘上。