红黑树(删除)
我们在给红黑树插入一个节点的时候我们走的是先插入然后再调整颜色这一路线。这里我们在给红黑树进行删除某一个节点的时候也一样走的是先删除某一个节点,然后对红黑树的颜色进行调整的路线。
这里我们不妨再次回顾一下之前文章所提到的关于红黑树的五条性质:
性质1 每个节点要么是红色的要么是黑色的
性质2 根节点一定是黑色的
性质3 每个叶子节点肯定是黑色的
性质4 一个红色节点的父亲节点一定不是红色的
性质5 任何一个节点到叶子节点的简单路径上所包含的黑色节点的数量是相同的
红黑树中删除指定节点和删除二叉树中的指定节点的操作大体是一样的,只不过红黑树相比二叉排序树多了一些关于颜色上的操作而且在删除完之后我们需要对颜色进行调整来使得删除后的红黑树重新满足红黑树的五条性质。这里我们大方向上分为两种情况来讨论:
情况1 节点z的右孩子节点为叶子节点
我们可以使用节点l来替换掉节点z,然后将节点l变为黑色。
情况2 节点z的右孩子节点不是叶子节点
面对这种情况我们采取的策略是在节点z的右子树中寻找值最小的节点r作为节点z的替代节点,然后在节点r替换掉节点z之后令节点r保持节点z原有的颜色,在使用节点r替换节点z之前我们还需要使用节点r的右孩子节点x来替换节点r,我们知道节点r既有可能是红色也有可能是黑色针对这两种可能我们分类讨论:
情况2.1 节点z的替换节点r的颜色为红色
遇到这种情况当我们使用节点r的替换节点x来替换节点r的时候,节点x不必变色,只需要保持自己原有的颜色就好,这样做并不会违背红黑树中的任何一条性质。
情况2.2 节点z的替换节点r的颜色为黑色
我们首先要使用节点r的右孩子节点x来替换节点r。节点x既有可能是红色,也有可能是黑色,既有可能是左孩子又有可能是右孩子,接下来我们以节点x为左孩子的情况为例,以节点x的不同颜色来进行分类讨论:节点x为右孩子的情况仅需要将节点x为左孩子的情况的代码中的left变为right,right变为left即可。
情况2.2.1 节点r的颜色为黑色,替换节点x的颜色为红色
遇到这种情况我们在使用节点x替换掉黑色的节点r,这样会导致包含节点x的路径相较于其他路径缺少一个黑色节点,从而违背了性质5,所以我们可以直接将节点x的颜色由红色变为黑色,这样就不会违背红黑树的性质5以及其他各项性质。
情况2.2.2 节点r的颜色为黑色,替换节点x的颜色为黑色
遇到这种情况当我们首先使用节点r的右孩子节点x来替换节点r,但是节点r为黑色,节点x也为黑色,在节点r被节点x替换后,包含节点x的路径相较于其他路径必然会缺少一个黑色节点,这样就破坏红了黑树的性质5。为了避免这种情况发生我们在节点r为黑色且其替换节点x也为黑色的时候,令x在保持自身黑色的情况下可以额外再增加一层黑色,这样节点x就有了双重黑色相当于两个黑色节点,在拥有双重黑色的节点x替换原有颜色为黑色的节点r的时候,我们就不会破坏红黑树的性质5。虽然我们这样做没有破坏红黑树的性质5,但是我们却破坏了红黑树的性质1。那接下来我们的主要任务就是不破坏性质5的前提下如何去掉节点x上的一层黑色使其变为单黑色,使得其能够保持红黑