在这篇文章中,我主要是将数据结构中的2-3树、2-3-4树、红黑树进行了整理。由于本篇字数、图片以及代码较多,可选择自己比较在于的部分阅读,但我建议是从上往下依次阅读。

毕竟大部分人可能比较关心红黑树。但是怎么是从2-3到红黑树的,这个过程是很值得了解的。而在文章的最后,我也大致手撸了一套2-3树相关操作的代码。

一、2-3树

一颗2-3树中的每个结点的度为2,或者3;其中度为2的称为2节点,度为3的称为3节点。

该树或者为空,或者满足以下性质:

  • 每个内部节点可以是2节点,也可以是一个3节点。2节点存放一个元素,3节点存放两个元素

  • 2节点 :的两个子节点分别是:left_child, middle_child;该节点的存放元素为data_l,该元素的关键字为data_l.key。
    以left_child为根的子树中所有节点的关键字(data_l.key)都小于该节点的data_l.key;以middle_child为根的子树中所有节点的关键字都大于该节点的data_l.key;

  • 3节点 :的三个子节点分别是:left_child, middle_child, right_child;该节点存放的两个元素分别为data_l, data_r。它们对应的元素关键字为data_l.key,data_r.key。
    以left_child为根的子树中所有节点关键字(data_l.key)都小于data_l.key;以middle_child为根的子树所有节点都大于data_l.key,小于data_r.key;以right_child为根的子树所有节点都大于data_r.key;

  • 4、所有的外部节点都位于同一层 (null节点)。

查找

1)、首先我们查看是2节点,还是3节点。通过查看data_r是否为INT_MAX(由于0可能是正常存储的元素,因此这里取的是INT_MAX)来确定,如果为INT_MAX则为2节点;

2)、如果是2节点:小于则沿着left_child查找,大于则沿着middle_child查找;相等则查找成功;

3)、如果是3节点:小于data_l则沿着left_child,大于data_l且小于data_r则沿着middle_child,大于data_r则沿着right_child;如果相等则查找成功

插入操作

当待查关键字不在2-3树中时,查找过程中将遇到唯一的叶节点(空节点)。如果节点只包含一个元素,那么就可以将新元素插入到该节点中。以构成3节点;

插入操作相对来说要复杂一点,但是理解透彻了也并不复杂。下面来仔细看一下插入过程,这里以插入数字30为例;

1)、首先我们的初始2-3树如下:

2)、现在我们插入数字30,它大于20,因此它应该处于3节点(B)的right_child里面。但是我们看看上面2-3树的性质4:所有的外部节点都位于同一层,所以现在我将30放入节点B这一层:

3)、但这明显不是2-3树,它存在了既不是2节点,也不是三节点的节点,因此我们需要改造它。改造的方法就是将20向上提:

4)、没办法,这又不符合预期。它依然违反了性质4,因此我们还需要改动。继续提20:

到这里我们大致上完成了2-3树中插入30的操作。主要就是先找到最直观的插入地址,然后一步一步的去更新该树,以符合2-3树的性质。

可以简单的理解2-3树的插入操作是从叶子节点向上生长的过程

下面我们来看一个更加复杂的插入例子。为了画图简单起见,2-3节点中的2节点的另一个data_r,以及每个为空的叶子节点就不画出了,因此下图中只有一个数据域的为2节点,有两个数据域的为3节点。下面以插入数字50为例:

这是类似的,就是节点向上移动的过程。我们大致看了一下插入操作,就是不断去满足2-3树的性质的同时去做节点上移的事儿。

下面我们再来看看2-3树的删除操作。

删除操作(旋转和合并)

后面的删除都以下面这棵树为基础进行:

非叶节点删除

首先,如果要删除的元素不在叶节点中,则可以用一个叶节点中的适当元素与待删除元素进行交换,从而将该删除操作转化为在叶节点上的删除操作。

一般情况下,我们可以用被删除元素的左子树中关键字最大的元素,或者右子树中关键字最小的元素与该元素交换。

总的来说就是把非叶节点的删除转换为叶节点的删除操作,而叶节点的删除操作又分为2节点和3节点删除操作。

3叶节点删除

3节点的删除操作相对比较简单,大致的规则如下:

  • 1)、如果要删除3节点的data_l时,当删除之后需要将data_r的关键字移动到data_l处。并且将data_r清零或者置为一个最大值即可;

这是以上面基础2-3树删除3节点中的data_l(10)域之后的结果。

  • 2)、如果要删除3节点的data_r时,直接将其清零或者置为一个最大值即可;

这里是将基础2-3树删除3节点中data_r(70)域之后的结果。

2叶节点删除

对于2节点的删除操作相对比较复杂一点,它并不能像3节点那样简单的删除就行了。因为2节点直接删除对应的data_l域的话,将会导致整个节点变为空。因此需要分多种情况来讨论:

旋转

待删除节点为2节点,且该节点的相邻兄弟子树有一个是3节点时我们使用旋转的操作。

  • 1)、待删除元素为左儿子,并且其中右边的兄弟子树(只看相邻兄弟子树)为3节点;

其中x为待删除节点的元素。

  • 2)、待删除元素为中儿子,并且其左兄弟或者右兄弟为3节点;

其中x为待删除节点的元素。

  • 3)、待删除元素为右儿子,并且其中左边兄弟子树(只看相邻兄弟子树)为3节点;

旋转操作不删除节点!!!

合并

旋转解决了当被删除元素为2节点,并且其左右两边的兄弟子树存在3节点的情况。那如果被删除节点左右两边都不存在3节点时,需要怎么处理呢?
这时候就需要用到合并操作。

合并操作用于2节点删除时,其左右兄弟同样为2节点时!
合并操作会删除节点!!!

和旋转类似,我们同样需要看被删除元素所在节点的位置。由于待删除节点左右兄弟子树存在3节点时都可以使用旋转的操作,所以以下所有的情形中所有待删除元素的相邻子树中都不会不会存在3节点。

下面具体的合并分类:

  • 1)、待删除节点为左儿子;


这里当父节点未3节点时,变换的第二步时如果其右子树为2节点时,我们同样可以将b下降到右子树中,而a保持不变。

  • 2)、待删除节点为中儿子;

过渡态中:c<a<b<d,结果的合并基于该大小关系。

  • 3)、待删除节点为右儿子;

过渡态中:c<a<d<b,结果的合并基于该大小关系。

删除操作总结

1)、非叶子节点,先将其转换为叶子节点之后操作;

2)、3节点删除直接删除即可,只不过需要注意剩下元素必须在data_l中;

3)、2节点的删除一定要牢记2-3树的四条性质来进行旋转和合并操作;

4)、节点变化的基础是我们在定义2-3树时,左儿子、中儿子、右儿子,以及节点的左右数据域的大小关系。

很显然,执行一次旋转和执行一次合并操作的时间复杂度为O(1)。如果执行的是(删除中的)旋转操作,那么一次旋转完成后删除就会结束;

在删除过程中,执行的合并操作次数不会超过2-3树的高度。因此对于包含n个节点的2-3树,其删除操作的时间复杂度为O(logn);

二、2-3-4树

2-3-4树是对2-3树的扩展,其中允许4节点(也就是最多有4个儿子)。它满足的性质和2-3树是类似的,主要还是在他们的大小关系上。下图主要是描述的4节点的结构,2节点和3节点从左到右依次为一个元素(data_l)和两个元素(data_l, data_m)已经对应的子节点:

大小关系如下:

1)、left_child.data_l.key < lef_child.data_m.key < left_child.data_r.key < root.data_l.key;

2)、root.data_l.key < left_mid_child.data_l.key < ... < root.data_m.key;

3)、root.data_m.key < right_mid_child.data_l.key < ... < root.data_r.key;

4)、root.data_r.key < right_child.data_l.key < ... < right_child.data_r.key;

2-3-4树也要满足所有的外部节点都在同一层上;

如果一颗高度为h的2-3-4树中只包含2节点,那么该树共有(2^h) - 1个元素(元素个数,不是节点个数);如果只包含4节点,那么该树共有(4^h) - 1个元素。因此一颗2-3-4树的元素个数为2^h - 1 到 4^h - 1个元素。
同样来说包含n个元素的2-3-4树,其高度范围log4(n+1)到log2(n+1)之间。下图是一个2-3-4树的具体例子:

插入操作(拆分4节点、向上移动)

插入操作我们可以和2-3树做一样的操作,即先从根节点到叶节点向下执行,然后从叶节点到根节点的向上扫描,并逐级调整以满足2-3-4树的性质。

但是对于2-3-4树存在更加高效的方式:

我们从根节点开始扫描,当扫描到4节点时就对该节点进行拆分操作,主要是看当前4节点父节点来进行适当的拆分操作。依次循环下去,那么到叶子节点时就能保证叶子节点为2节点或者3节点

对于一个4节点,需要考虑以下三种不同的情况:

  • 1)、4节点是2-3-4树的根节点

根节点的拆分会使得2-3-4树的高度增加1。并且拆分之后得到的两个节点都是 2节点

  • 2)、4节点的父节点是一个2节点


上半部分中4节点作为2节点的左子树,下半部分为4节点作为2节点的右子树。拆分之后得到的两个节点同样都是 2节点

  • 3)、4节点的父节点是一个3节点

拆分之后得到的两个节点同样都是 2节点

到这儿我们就能大致看出规律了:

4节点的data_m向上提,data_l和data_r自成一个2节点

2-3-4树插入实例

以下图为原2-3-4树执行插入操作:

1、首先我们插入元素5:从根节点开始扫描,发现根节点为4节点。因此使用第一点中的拆分过程,将4节点的中data_m向上提,独立成一个2节点。此时会使得树的总体高度增加1。然后依次寻找5所在的位置,发现目标叶子节点为一个3节点,符合插入要求,直接插入即可。

2、插入元素14:从根节点开始扫描,发现包含元素【5,12,15】的节点为4节点,而该节点父节点为2节点。因此我们可以使用上面第二点“4节点为父节点是一个2节点”的拆分方法。拆分完成后继续寻找元素14的插入点,发现节点【15】为2节点直接插入。

比如这里插入一个元素77和这个例子很类似。发现节点【72,80,90】为4节点,把元素80向上提,构成新的节点【70,80,99】。然后把元素77插入到节点【72】的右子节点中即可。

因此2-3-4树的插入操作对于2-3树插入操作的优势在于,只需自顶向下单次扫描就可以完成;而2-3树需向下扫描之后,还有元素向上提的过程。

删除操作(合并4节点、向下移动)

插入操作虽然和2-3树类似,但是需要有效率上的改进。如果没有优势的话,那该查找树存在也没有什么意义。

删除任何元素都可以化简为删除某个叶子节点中的元素。

如果 删除元素所在的叶节点是3节点或者4节点 ,直接删除即可。结果分别变成2节点和3节点 ;

我们可以从根节点到叶节点的向下扫描过程中对2-3-4树进行更新,以达到删除元素时,元素所在叶节点为3节点或者4节点。这样我们就可以避免在类似2-3树删除操作(从叶节点到根节点向上)出现的重建步骤。

向下扫描2-3-4树并进行更新时要求:每当查找移向下一层节点时,该节点必须是3节点或者4节点

为了描述方便,这里假设当前节点为p,而将要移到的下一个节点为q,也就是说q是p的子节点。r节点为q节点的兄弟节点,当q是p的left_child时,r节点为p的left_mid_child;否则q最近的兄弟节点r就是其左边的兄弟节点。如果看起来有点不顺口,直接对应下面图就行了。
下面列出5种情况:

  • 1)、p(父节点)是叶子节点 :此时待删除元素要么在节点p中,要么不存在;

  • 2)、q不是2节点:那就是3节点或者4节点,不需要更新。继续寻找下一个节点;

  • 3)、q是2节点且其兄弟节点r为2节点:将p、q、r合并成一个4节点。这个过程其实就是2-3-4树插入过程的逆过程(也就是插入里面的三种情况)。其中p节点分为2节点、3节点、4节点;

  • 4)、q是2节点且其兄弟节点为3节点

这里有个错误,下半部分的应该是y上移动.

  • 5)、q是2节点且其兄弟节点为4节点

第四种和第五种非常类似。

2-3-4树删除实例

下面我们来看一个2-3-4树删除元素的实例。在下面的例子中我们删除元素74:

三、红黑树

从2-3-4树到红黑树

红黑树相对于2-3-4树能够更有效地节省存储空间,因为对于2-3-4树而言,它如果存在2节点或者3节点是存在data_l或者data_m是没有使用而浪费了。在红黑树中,每个节点的儿子指针分为:红色和黑色两种。在本文中:

1)、红色指针:红色节点表示从父节点指向该节点的指针为红色指针。红色指针用虚线表示;

2)、黑色指针:黑色节点表示从父节点指向该节点的指针为黑色指针。黑色指针用实线表示;

红黑树是2-3-4树的二叉树表示,因此我们来看一下2-3-4树到红黑树的转变过程:

  • 2-3-4树种的2节点:把一个2节点p表示为一个红黑树节点q。红黑树该节点左右子节点均为黑色;

1
2
3
q.data = p.data_l;
q->left_child = p->left_child;
q->right_child = p->left_mid_child;
  • 2-3-4树种的3节点:把一个3节点表示为2个红黑树节点,其中一个节点作为另一个节点的子节点。并且子节点为红色;

  • 2-3-4树种的4节点:把一个4节点表示为3个红黑树节点,其中data_m所在节点为父节点,左右子节点用红色表示;

下面是将上面2-3-4树转换成红黑树的例子:

红黑树性质

我们从上面一节得出的红黑树,可以知道红黑树具有如下性质:

  • 1)、红黑树是一颗二叉查找树;
  • 2)、根节点为黑色节点;
  • 3)、所有根节点到外部节点的路径上黑色指针个数相同(同样的黑色节点也相同)。这是因为在2-3-4树中所有外部节点都位于同一层,而在该树种指针都是黑色指针;
  • 4)、任何从根节点到外部节点的路径上都不存在两个连续的红色指针;

下面是红黑树大致的结构:

1
2
3
4
5
6
7
8
9
10
typedef struct red_black_tree* red_black_ptr;
typedef struct red_black_tree {
        element data;
/// 左右儿子
        red_black_ptr left_child;
        red_black_ptr right_child;
/// 两个颜色域
        color left_color;
        color right_color;
}red_black;

红黑树的插入

红黑树的插入可以按照两种方式:自顶向下(Top-To-Down),自底向上(Down-To-Top)。自顶向下只需从根到叶节点一次扫描即可;而自底向上需要从根节点到叶节点扫描之后,还需要继续从叶节点到根节点扫描一次。

👻🍄👻自顶向下的插入

通过观察当前节点的两个颜色域是否都为红色。如果都为红色,那么该节点对应2-3-4树中的4节点(详细可以看上面2-3-4树到红黑树的转换过程)。当发现4节点时:

  • 第一步、将该节点的两个颜色域都变为黑色(由红变黑);

  • 第二步、如果该节点是其父节点的左儿子、或者右儿子,则将其父节点的左颜色域、或者右颜色域变为红色;

  • 第三步、如果此时树中出现两个连续的红色指针时,则需要类似AVL树的LL、LR、RL、RR旋转操作;

由于前面有了2-3-4树的基础知识,我们以2-3-4树的2节点、3节点、4节点,来总结红黑树插入时旋转和变色的规律:

每插入一个元素时,我们自顶向下遍历每一个节点:

1)、如果是2节点、或者3节点,则保持它们性质不发生改变(至于怎么判断红黑树中当前节点是2节点,还是3节点。请看“从2-3-4树到红黑树”一节);

变色

2)、如果当前节点是4节点时(红黑树中其左右指针必定指向红色节点),则将其左右指针和左右子节点变为黑色。这里是将当前4节点作为父节点而言的;

3)、如果当前节点是4节点时,并且该节点作为其父节点左子节点、或者右子节点,那么将其父节点对应的左指针或者右指针变为红色,并且当前节点也变为红色;
这里是将该节点作为其父节点的子结点而言的。

旋转

4)、如果出现连续两个红色指针时,就需要做对应的旋转操作;

红黑树插入实例例一:

下面先来看一个最简单的例子,我们一次将1,2,3,4,5,6,7,8 插入到红黑树中:

自顶向下的插入过程,是在从根节点到需要插入的目的节点开始进行遍历,并且在遍历过程中对红黑树进行变色和旋转。

自底向上插入

自底向上的插入,首先需要查找关键字在红黑树的插入位置。显然这个插入操作是不成功的查找,且在该 向下查找过程中不需要进行旋转变换,只需要将待插元素作为最后遇到的节点的某个子节点,并用红色指针将其与它父节点连接

由于每次以红色指针插入,所以此时所有根节点到外部节点路径上黑色节点的数量相同,但有可能存在两个连续红色指针。

出现两个连续的红色指针时

假设连续出现的两个红色指针分别为 。 这表示q作为p的子节点,r作为q的子节点: p —> q —> r;因此p、q、r之间存在四种情况:

1)、LL: q作为p的左子节点,r作为q的左子节点;

2)、LR: q作为p的左子节点,r作为q的右子节点;

3)、RL: q作为p的右子节点,r作为q的左子节点;

4)、RR: q作为p的右子节点,r作为q的右子节点;

现在假设s作为q的兄弟(如果s不为空,即存在兄弟节点),

变色

当s节点(q的兄弟节点)为红色节点时需要做变色操作:

节点p变为红色节点;节点q,s变为黑色节点;节点r不变。这样做变色操作可能会导致红色指针冲突沿着树向上传播,所以颜色调整过程需要多次重复。

颜色调整不会影响从根节点到外部节点路径上黑色指针的个数

旋转

当出现连续两个红色指针,并且节点s为黑色节点时,此时需要做旋转操作。

旋转操作不会引起红色指针冲突的传播,因此最多只需要执行一次旋转操作

红黑树插入实例例二:

现在使用自底向上的方式按顺序插入元素10,9,8,7,6,5,4,3:

1)、插入节点颜色为红色;

2)、节点s为红色时,并且q和r为两个连续的红色节点,此时则需要变色;

3)、如果节点s为黑色,或者为空。当q和r为两个连续红色节点时,此时只需要旋转即可;

自顶向下和自底向上的总结

1)、对于自顶向下的插入方法,需要执行O(logN)次旋转操作;而自底向上的插入方法只需要执行一次旋转操作;

2)、两种方式都需要执行O(logN)颜色调整操作;

使用自底向上的插入方式就和网上大部分提到的红黑树操作方式一样。但我们还是需要知道自顶向下的操作方式。

红黑树的删除

其实讲到这里,红黑树已经没有什么讲的必要了。只需要套用2-3-4树的删除节点策略即可。最主要的是在自顶向下扫描的过程中,明确当前红黑树节点处于对应2-3-4树节点的类型。

扫描过程:

  • 1)、尚未命中待删除元素时,则以二叉树大小关系,去寻找合适的左右子树;

  • 2)、命中待删除元素时,如果元素所处节点为叶子节点。那么直接删除即可;

  • 3)、命中待删除元素时,如果元素所处节点不是叶子节点,此时我们可以像2-3树/2-3-4树的规则继续向下寻找叶子节点。寻找的目标可以是命中节点的左子树中最大子节点,或者右子树中最小子节点;

明确节点类型:

  • 1)、如果当前节点是红色节点,那么该节点一定对应于2-3-4树中的3节点、或者4节点;
    由于2-3-4树中,3节点和4节点无需变换直接向下继续遍历即可

  • 2)、如果当前节点是黑色节点,那么再去查看该节点左右子节点是否存在红色节点。
    如果没有红色节点,那么该节点即对应2-3-4树中的2节点。此时则需要看该节点相邻子树的情况,进行对应2节点到4节点的变换(具体变换过程见2-3-4树的删除一节)。

下面是一个具体的例子,在这个例子中我将要删除元素80:

源代码

由于需要写的代码太多了,而且我又比较懒。所以我就写了一下2-3树的增加、删除等相关操作,我将代码全部贴在这里,也可以直接去Github上查看源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
#include <iostream>
#include <stdio.h>
#include <list>
#include <stdlib.h>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <set>
#include <vector>
using namespace std;
/// 这里假设对于element来说,如果该域值不存在,我们使得element的value部分设置为INT_MAX
class element {
private:
int value;
public:
element(int val) :value(val) {}
element() { value = INT_MAX; }
void setValue(int val) {value = val;}
int getValue() const { return value; }
static inline element invalid() {
return element(INT_MAX);
}
};
bool operator == (const element& lhs,const element& rhs) {
return lhs.getValue() == rhs.getValue();
}
bool operator != (const element& lhs,const element& rhs) {
return !(lhs.getValue() == rhs.getValue());
}
class two_three_tree_node {
public:
element data_l;
element data_r;
two_three_tree_node* left_child;
two_three_tree_node* middle_child;
two_three_tree_node* right_child;
public:
two_three_tree_node()
{
data_l = element::invalid();
data_r = element::invalid();
left_child = NULL;
middle_child = NULL;
right_child = NULL;
}
virtual ~two_three_tree_node()
{
data_l = element::invalid();
data_r = element::invalid();
if (left_child != nullptr)
{
delete left_child;
}
if (middle_child != nullptr)
{
delete middle_child;
}
if (right_child != nullptr)
{
delete right_child;
}
}
};
class node_strategy {
protected:
const two_three_tree_node* node;
element value;
public:
node_strategy():node(NULL),value(element::invalid()) {
}
virtual void setValue(const element& ele) = 0;
virtual void setNode(const two_three_tree_node* nd) = 0;
virtual two_three_tree_node* next() = 0;
virtual ~node_strategy()
{
}
};
class left_child_strategy:public node_strategy {
two_three_tree_node* next() {
element data_left = node->data_l;
if (value.getValue() < data_left.getValue()) { return node->left_child; }
return nullptr;
}
void setValue(const element& ele) {
value = ele;
}
void setNode(const two_three_tree_node* nd) {
node = nd;
}
};
class middle_child_strategy :public node_strategy {
two_three_tree_node* next() {
element data_left = node->data_l;
element data_right = node->data_r;
if (value.getValue() > data_left.getValue() && value.getValue() < data_right.getValue()) { return node->middle_child; }
return nullptr;
}
void setValue(const element& ele) {
value = ele;
}
void setNode(const two_three_tree_node* nd) {
node = nd;
}
};
class right_child_strategy :public node_strategy {
two_three_tree_node* next() {
element data_right = node->data_r;
if (value.getValue() > data_right.getValue()) {
return node->right_child;
}
return nullptr;
}
void setValue(const element& ele) {
value = ele;
}
void setNode(const two_three_tree_node* nd) {
node = nd;
}
};
///#######################################################################################################################
///#######################################################################################################################
/// #### 查找
///#######################################################################################################################
///#######################################################################################################################
class search_strategy {
two_three_tree_node* root;
public:
search_strategy(two_three_tree_node* rt) {
root = rt;
}
two_three_tree_node* search(element& ele) {
two_three_tree_node* node = root;
node_strategy *left = new left_child_strategy();
node_strategy *middle = new middle_child_strategy();
node_strategy *right = new right_child_strategy();
while (node)
{
if (node->data_l == ele)
{
return node;
}
if (node->data_r == ele)
{
return node;
}
left->setNode(node);
left->setValue(ele);
if (two_three_tree_node *temp = left->next())
{
node = temp;
continue;
}
middle->setNode(node);
middle->setValue(ele);
if (two_three_tree_node * temp = middle->next())
{
node = temp;
continue;
}
right->setNode(node);
right->setValue(ele);
if (two_three_tree_node * temp = right->next())
{
node = temp;
continue;
}
node = nullptr;
}
delete left;
delete middle;
delete right;
return nullptr;
}
};
///#######################################################################################################################
///#######################################################################################################################
/// #### 插入
///#######################################################################################################################
///#######################################################################################################################
class insert_strategy {
private:
/// 创建一个栈结构,将从叶节点到根节点路径上左右的节点保存下来
struct find_stack {
struct find_stack_node {
two_three_tree_node* tree_node;
find_stack_node* next;
};
void push(const two_three_tree_node* tree_node) {
if (!tree_node)
{
return;
}
find_stack_node* node = new find_stack_node();
node->tree_node = const_cast<two_three_tree_node*>(tree_node);
node->next = top;
top = node;
}
two_three_tree_node* pop() {
find_stack_node* node = top;
top = top->next;
two_three_tree_node* tree_node = node->tree_node;
node->next = nullptr;
node->tree_node = nullptr;
delete node;
return tree_node;
}
find_stack_node* stack_top() {
return top;
}
~find_stack()
{
while (top)
{
pop();
}
}
private:
find_stack_node* top;
};
///#######################################################################################################################
///#######################################################################################################################
///#####寻找节点
///#######################################################################################################################
///#######################################################################################################################
class find_element {
private:
two_three_tree_node* root;
element value;
find_stack* stack;
public:
find_element(const two_three_tree_node* rt, element val) {
root = const_cast<two_three_tree_node*>(rt);
value = val;
stack = new find_stack();
}
void set_value(element val) {
value = val;
}
/// 修改版查找:根据根节点和指定元素:如果查找到指定元素,则认为查找成功,返回null;否则返回查找过程中遇到的叶子节点;
two_three_tree_node* node() {
two_three_tree_node* node = root;
node_strategy* left = new left_child_strategy();
node_strategy* middle = new middle_child_strategy();
node_strategy* right = new right_child_strategy();
two_three_tree_node* result = nullptr;
while (node)
{
stack->push(node);
if (node->data_l == value)
{
goto release;
}
if (node->data_r == value)
{
goto release;
}
left->setNode(node);
left->setValue(value);
if (two_three_tree_node * temp = left->next())
{
node = temp;
continue;
}
middle->setNode(node);
middle->setValue(value);
if (two_three_tree_node * temp = middle->next())
{
node = temp;
continue;
}
right->setNode(node);
right->setValue(value);
if (two_three_tree_node * temp = right->next())
{
node = temp;
continue;
}
node = nullptr;
}
if (stack->stack_top())
{
result = stack->stack_top()->tree_node;
}
release:
delete left;
delete middle;
delete right;
return result;
}
find_stack* get_stack() {
return stack;
}
~find_element()
{
root = nullptr;
delete stack;
stack = nullptr;
}
};
//// 拼接
class split_element {
private:
find_stack* stack;
element ele;
public:
split_element(const find_stack* steck,const element& val) {
stack = const_cast<find_stack *>(steck);
ele = val;
}
two_three_tree_node* split(bool (*two_node_insert_handle)(two_three_tree_node* node,const two_three_tree_node* insert_node)){
find_stack::find_stack_node* top = stack->stack_top();
two_three_tree_node* be_insert_node = new two_three_tree_node();
be_insert_node->data_l = ele;
int breakpoint = ele.getValue();
while(be_insert_node->data_l != element::invalid() && top){
two_three_tree_node* current = top->tree_node;
if (two_node_insert_handle(current, be_insert_node)) {
return nullptr;
}
/// current 存放三个元素里面最小的一个
/// max 存放三个元素里面最大的一个
two_three_tree_node* max_item = new two_three_tree_node();
if (be_insert_node->data_l.getValue() < current->data_l.getValue())
{
max_item->data_l = current->data_r;
max_item->data_r = element::invalid();
max_item->left_child = current->middle_child;
max_item->middle_child = current->right_child;
element temp = current->data_l;
current->data_l = be_insert_node->data_l;
current->data_r = element::invalid();
current->left_child = be_insert_node->left_child;
current->middle_child = be_insert_node->middle_child;
current->right_child = nullptr;
be_insert_node->data_l = temp;
be_insert_node->data_r = element::invalid();
be_insert_node->left_child = current;
be_insert_node->middle_child = max_item;
top = top->next;
continue;
}
if (be_insert_node->data_l.getValue() > current->data_r.getValue()) {
max_item->data_l = be_insert_node->data_l;
max_item->data_r = element::invalid();
max_item->left_child = be_insert_node->left_child;
max_item->middle_child = be_insert_node->middle_child;
current->right_child = nullptr;
element temp = current->data_r;
current->data_r = element::invalid();
be_insert_node->data_l = temp;
be_insert_node->left_child = current;
be_insert_node->middle_child = max_item;
be_insert_node->data_r = element::invalid();
top = top->next;
continue;
}
if (be_insert_node->data_l.getValue() < current->data_r.getValue() && be_insert_node->data_l.getValue() > current->data_l.getValue()) {
max_item->data_l = current->data_r;
max_item->left_child = be_insert_node->middle_child;
max_item->middle_child = current->right_child;
max_item->data_r = element::invalid();
current->middle_child = be_insert_node->left_child;
current->data_r = element::invalid();
current->right_child = nullptr;
be_insert_node->left_child = current;
be_insert_node->middle_child = max_item;
be_insert_node->right_child = nullptr;
be_insert_node->data_r = element::invalid();
top = top->next;
continue;
}
}
return be_insert_node;
}
};
static bool two_node_insert(two_three_tree_node* node, const two_three_tree_node* insert_node) {
if (node->data_r != element::invalid())
{
return false;
}
if (node->data_l.getValue() < const_cast<two_three_tree_node*>(insert_node)->data_l.getValue())
{
node->data_r = insert_node->data_l;
node->middle_child = insert_node->left_child;
node->right_child = insert_node->middle_child;
}
else
{
element temp = node->data_l;
node->data_l = insert_node->data_l;
node->data_r = temp;
node->right_child = node->middle_child;
node->left_child = insert_node->left_child;
node->middle_child = insert_node->middle_child;
}
return true;
}
public:
two_three_tree_node* insert(two_three_tree_node* root ,const element &ele) {
find_element* fele = new find_element(root,ele);
two_three_tree_node* leaf = fele->node();
if (nullptr == leaf)
{/// 待插入元素已存在于树中
delete fele;
return root;
}
split_element* se = new split_element(fele->get_stack(), ele);
two_three_tree_node* root_node = se->split(two_node_insert);
if (root_node == nullptr) {/// 2节点
delete fele;
return root;
}
/// 3节点
delete fele;
return root_node;
}
};
///#######################################################################################################################
///#######################################################################################################################
/// #### 删除
///#######################################################################################################################
///#######################################################################################################################
class delete_strategy {
two_three_tree_node* root;
element ele;
private:
/// 获取兄弟节点;
two_three_tree_node* get_bro_node(two_three_tree_node * const node, two_three_tree_node * const parent) {
if (node == parent->left_child)
{
return parent->middle_child;
}
if (node == parent->middle_child)
{
if (is_three_node(parent->right_child))
{
return parent->right_child;
}
return parent->left_child;
}
if (node == parent->right_child)
{
return parent->middle_child;
}
return nullptr;
}
protected:
static inline bool is_three_node(two_three_tree_node* node) {
if (nullptr == node)
{
return false;
}
if (node->data_l != element::invalid() && node->data_r != element::invalid())
{
return true;
}
return false;
}
static bool remove_element(two_three_tree_node* node, element ele) {
if (node->data_r == ele)
{
node->data_r = element::invalid();
return true;
}
if (node->data_l == ele) {
node->data_l = node->data_r;
node->data_r = element::invalid();
return true;
}
return false;
}
class delete_ttt_node {
public:
two_three_tree_node* node;
element* isptr;
delete_ttt_node(const two_three_tree_node* rt, const element* is) {
node = const_cast<two_three_tree_node*>(rt);
isptr = const_cast<element*>(is);
}
};
/// 叶节点转移
class leaf_swap {
delete_ttt_node* ttt_node;
element ele;
/// 返回值为目标节点
/// leaf为叶节点
private:
two_three_tree_node* leaf_node;
two_three_tree_node* leaf_parent_node;
public:
leaf_swap(const two_three_tree_node* rt, element& el) {
ttt_node = new delete_ttt_node(rt, nullptr);
ele = el;
leaf_node = nullptr;
leaf_parent_node = nullptr;
}
leaf_swap() {
ttt_node = new delete_ttt_node(nullptr, nullptr);
ele = element::invalid();
leaf_node = nullptr;
leaf_parent_node = nullptr;
}
~leaf_swap()
{
delete ttt_node;
}
two_three_tree_node* get_leaf_node() {
return leaf_node;
}
two_three_tree_node* get_leaf_parent_node() {
return leaf_parent_node;
}
delete_ttt_node* get_swap_info(two_three_tree_node** leaf) {
two_three_tree_node* node = ttt_node->node;
delete_ttt_node* des_node = new delete_ttt_node(ttt_node->node, nullptr);
node_strategy* left = new left_child_strategy();
node_strategy* middle = new middle_child_strategy();
node_strategy* right = new right_child_strategy();
/// 命中待删除元素
while (node)
{
if (node->data_l == ele)
{
des_node->node = node;
des_node->isptr = &(node->data_l);
break;
}
if (node->data_r == ele)
{
des_node->node = node;
des_node->isptr = &(node->data_r);
break;
}
left->setNode(node);
left->setValue(ele);
if (two_three_tree_node * temp = left->next())
{
leaf_parent_node = node;
node = temp;
continue;
}
middle->setNode(node);
middle->setValue(ele);
if (two_three_tree_node * temp = middle->next())
{
leaf_parent_node = node;
node = temp;
continue;
}
right->setNode(node);
right->setValue(ele);
if (two_three_tree_node * temp = right->next())
{
leaf_parent_node = node;
node = temp;
continue;
}
node = nullptr;
}
delete left;
delete middle;
delete right;
/// 寻找叶子节点
/// 左子树的最大子节点;或者右子树的最小子节点;
/// 这里我选择左子树的最大子节点;
if (des_node == nullptr)
{
leaf_parent_node = nullptr;
return des_node;
}
*leaf = des_node->node;
for (node = (des_node->isptr->getValue() == des_node->node->data_r.getValue()) ? des_node->node->middle_child : des_node->node->left_child;
node;
node = node->middle_child)
{
/// 非叶节点
leaf_parent_node = *leaf;
*leaf = node;
}
return des_node;
}
bool swap() {/// 仅仅交换两个指针的数据域的值,指针域不做改变
two_three_tree_node* leaf = nullptr;
delete_ttt_node* des_node = get_swap_info(&leaf);
leaf_node = leaf;
if (nullptr == des_node || nullptr == leaf)
{
return false;
}
if (des_node->node == leaf)
{/// 叶节点,不做交换
return true;
}
if (leaf->data_r != element::invalid())
{
element r_temp = leaf->data_r;
leaf->data_r = *(des_node->isptr);
*(des_node->isptr) = r_temp;
}
else
{
element l_temp = leaf->data_l;
leaf->data_l = *(des_node->isptr);
*(des_node->isptr) = l_temp;
}
delete des_node;
return true;
}
};
class two_node_delete_interface {
protected:
two_three_tree_node* leaf;
two_three_tree_node* bro;
two_three_tree_node* parent;
two_node_delete_interface(two_three_tree_node* lf, two_three_tree_node* bo, two_three_tree_node* pt) :leaf(lf), bro(bo), parent(pt) {}
virtual ~two_node_delete_interface(){}
};
/// 旋转
class rotate : public two_node_delete_interface {/// 兄弟节点为3节点时,旋转
private:
bool left_leaf_rotate() {
leaf->data_l = parent->data_l;
leaf->data_r = element::invalid();
parent->data_l = bro->data_l;
bro->data_l = bro->data_r;
bro->data_r = element::invalid();
leaf->middle_child = bro->left_child;
bro->left_child = bro->middle_child;
bro->middle_child = bro->right_child;
return true;
}
bool right_leaf_rorate() {
leaf->data_l = parent->data_l;
parent->data_l = bro->data_r;
leaf->left_child = bro->right_child;
return true;
}
bool middle_leaf_rorate() {
if (bro == parent->right_child) {
leaf->data_l = parent->data_r;
leaf->data_r = element::invalid();
parent->data_r = bro->data_l;
bro->data_l = bro->data_r;
bro->data_r = element::invalid();
leaf->middle_child = bro->left_child;
bro->left_child = bro->middle_child;
bro->middle_child = bro->right_child;
return true;
}
leaf->data_l = parent->data_l;
parent->data_l = bro->data_r;
leaf->left_child = bro->right_child;
return true;
}
public:
rotate(two_three_tree_node* lf, two_three_tree_node* bo, two_three_tree_node* pt):two_node_delete_interface(lf, bo, pt) {}
bool execute() {
if (nullptr == leaf || nullptr == parent || nullptr == bro)
{
return false;
}
if (leaf == parent->left_child)
{
return left_leaf_rotate();
}
else if (leaf == parent->middle_child)
{
return middle_leaf_rorate();
}
else
{
return right_leaf_rorate();
}
}
};
/// 合并
class combine : public two_node_delete_interface {
protected:
bool left_leaf_combine() {
if (nullptr == leaf || nullptr == parent || nullptr == bro)
{
return false;
}
bool parent_is_three_node = is_three_node(parent);
if (false == parent_is_three_node)
{
parent->data_r = bro->data_l;
parent->left_child = leaf->left_child;
parent->middle_child = bro->left_child;
parent->right_child = bro->right_child;
delete bro;
delete leaf;
bro = nullptr;
leaf = nullptr;
return true;
}
bro->data_r = bro->data_l;
bro->data_l = parent->data_l;
parent->data_l = parent->data_r;
parent->data_r = element::invalid();
parent->left_child = parent->middle_child;
parent->middle_child = parent->right_child;
parent->right_child = nullptr;
bro->right_child = bro->middle_child;
bro->middle_child = bro->left_child;
bro->left_child = leaf->left_child;
delete leaf;
leaf = nullptr;
return true;
}
bool middle_leaf_combine() {
if (nullptr == leaf || nullptr == parent || nullptr == bro)
{
return false;
}
bool parent_is_three_node = is_three_node(parent);
if (false == parent_is_three_node)
{
parent->data_r = parent->data_l;
parent->data_l = bro->data_l;
parent->left_child = nullptr;
parent->middle_child = nullptr;
delete leaf;
delete bro;
leaf = nullptr;
bro = nullptr;
return true;
}
bro->data_r = parent->data_l;
parent->data_l = parent->data_r;
parent->data_r = element::invalid();
parent->middle_child = parent->right_child;
parent->right_child = nullptr;
bro->middle_child = leaf->left_child;
bro->right_child = leaf->middle_child;
delete leaf;
leaf = nullptr;
return true;
}
bool right_leaf_combine() {
if (nullptr == leaf || nullptr == parent || nullptr == bro)
{
return false;
}
bro->data_r = parent->data_r;
parent->data_r = element::invalid();
parent->right_child = nullptr;
bro->middle_child = leaf->left_child;
bro->right_child = leaf->middle_child;
delete leaf;
leaf = nullptr;
return true;
}
public:
combine(two_three_tree_node* lf, two_three_tree_node* bo, two_three_tree_node* pt) :two_node_delete_interface(lf, bo, pt) {}
bool execute() {
if (nullptr == leaf || nullptr == parent || nullptr == bro)
{
return false;
}
if (leaf == parent->left_child)
{
return left_leaf_combine();
}
else if(leaf == parent->middle_child)
{
return middle_leaf_combine();
}
else
{
return right_leaf_combine();
}
}
};
class two_node_delete : public two_node_delete_interface {
public:
two_node_delete(two_three_tree_node* lf, two_three_tree_node* bo, two_three_tree_node* pt):two_node_delete_interface(lf, bo, pt) {}
bool execute() {
if (nullptr == leaf || nullptr == parent || nullptr == bro)
{
return false;
}
/// 查看兄弟节点为2节点,还是3节点;
bool three_node = is_three_node(bro);
if (true == three_node) /// 兄弟节点为3节点,旋转
{
rotate* rtt = new rotate(leaf, bro, parent);
return rtt->execute();
}
else /// 兄弟节点为2节点,合并
{
combine* cbn = new combine(leaf, bro, parent);
return cbn->execute();
}
return false;
}
};
public:
delete_strategy(const two_three_tree_node*rt, element& el) {
root = const_cast<two_three_tree_node*>(rt);
ele = el;
}
bool execute() {
leaf_swap* ls = new leaf_swap(root, ele);
bool result = ls->swap();
if (false == result)
{
return false;
}
two_three_tree_node* leaf = ls->get_leaf_node();
if (nullptr == leaf)
{
return false;
}
two_three_tree_node* leaf_parent = ls->get_leaf_parent_node();
/// 3节点
if (is_three_node(leaf))
{
remove_element(leaf, ele);
return true;
}
/// 2节点
two_three_tree_node* bro = get_bro_node(leaf, leaf_parent);
if (nullptr == bro)
{
return false;
}
two_node_delete* tnd = new two_node_delete(leaf, bro, leaf_parent);
tnd->execute();
return result;
}
};
int main()
{
vector<int> randoms;
/// 插入
//cout << "input root node value: " << endl;
int rootvalue = 50;
//cin >> rootvalue;
two_three_tree_node* root = new two_three_tree_node();
root->data_l = element(rootvalue);
/* 自行定制输入数字
int inputvalue = 0;
while (cout << "input node (-1 exit): ", cin >> inputvalue,inputvalue != -1)
{
randoms.push_back(inputvalue);
}
*/
randoms = { 33 ,85 ,68 ,80 ,62 ,15 ,97 ,10 };
insert_strategy* ins = new insert_strategy();
for (vector<int>::iterator itr = randoms.begin(); itr != randoms.end(); itr++)
{
root = ins->insert(root, element(*itr));
}
/// 查找
search_strategy* search = new search_strategy(root);
element search_item(12);
bool search_result = search->search(search_item);
/// 删除
int val;
while (cout<<"input delete item: "<<endl,cin>>val,val!=-1) {
element be_deleted(val);
delete_strategy* delete_s = new delete_strategy(root, be_deleted);
delete_s->execute();
}
return 0;
}

文章内容较长,到这里基本上算是把2-3树、2-3-4树、以及红黑树都捋了一遍。如果存在错误,麻烦帮忙指出(可以微博联系我)。