计算机中的红与黑(三)
2、delete
相对于insert操作删除操作相对有点复杂。我们一步一步来。
同样这里的操作时基于对二叉搜索树的delete操作的。先看一下代码。
void rbtdelete(Node * root, Node * node){ Node * n = delete(root, node);// the return node n is the child node of the delete node node if(node->color==BLACK) rbtdelete_fixup(root,n); }
什么时候需要进行修复?如果删除的是一个红色节点,那么红黑性质肯定没有改变,因此不需要进行修复;如果删除的是一个黑色节点,那么被删除的节点所在的路径上黑节点的个数减一,因此红黑性质遭到了破坏,需要进行修复。由于被删除节点所在的子树,缺少了一个黑色节点,我们假设现在所指向的节点也就是他的孩子节点,多了一层黑色,如果原来这个节点是黑色的,那么现在他是双黑节点,如果原来是红色的,那么是红黑节点。这里的rbdelete_fixup算法可以将这个节点的多出来的那层黑色不断的往上移动,最后达到平衡的状态。
现在我们知道当前节点指向的是被删除的节点的子节点,这里有一个非常特殊的情况,如果在删除之前只有一个节点,那么删除之后就会出现为空树的情况,这时是没有必要进行修复的!
假设删除的是一个叶子节点,那么最后的子节点一定指向了NIL节点。
从红黑树的定义可以看出在整体上实际上这个NIL节点是没有父节点的,或者我们没有用到,它的作用体现在充当null的作用,所有的null孩子,根node的null父节点,都指向了这个节点。也就是默认这个NIL节点既没有孩子,也咩有父亲。但是当我们删除一个叶子节点的时候,会将其子节点,即这个NIL节点的父节点指针指向被删除的节点的父节点。
和插入操作类似,首先对所有的case进行分类,我们只考虑当前节点为其父节点左子结点的情况,如果为右子节点,和这里的情况是对称的。为了便于说明我们假设当前节点为x,它的父节点为f,兄弟节点为w
情景一、当x为红色的时候
这是最简单的情形了,由于被删除的节点是黑色,x正好在被删除的节点所在的子树当中(实际上两者都是所在子树的根节点),现在x是红色,将其改为黑色,那么就可以弥补删除原先节点的黑色节点缺一的情况。
下面考虑x为黑色节点的情况,这里的情形和insert操作是的情形正好相反,在insert当中当前节点(也就是插入的节点),它的父节点f,以及祖父节点ff都是确定的,所以使用它的叔节点作为划分的依据。但是这里的情况变味了及时父节点的颜色也是无法确定的。????为什么是使用兄弟节点作为划分的依据,不太清楚。
情景二、当x为黑色的时候,w为红色时候,根据红黑树的性质,我们知道w的上下左右不会出现红色节点,也就是全是黑色的
这是左边的子树几乎出于饱和的状态,看起来似乎没有扩充一个黑色节点的机会,我们对其进行一次左旋,将f染为红色,新的子树根节点w染为黑色,这时左子树多了一个节点,并且每条路径上的黑色节点的个数没有改变。
这是的新的当前节点没有改变仍然为x,似乎节点的层数下降了一层。有的人可能回想,这样下去,测试节点一会下,一会上,算法什么时候才能结束,实际上,从情形二导出的之后的每种可能都会是算法结束的状态。这是算法会进入下面的三种情形当中的的一种,即在兄弟节点为黑色的前提下,考虑兄弟节点的孩子节点进行进一步的分类的情形。
情景三、当x为黑色的时候,w为黑色的时候,w的两个孩子都是黑色的时候
由于x为双黑节点,那么x和w分别去掉一层黑色,同时将父节点作为新的判定节点。
这种情形会导致算法进入下次的循环。log(n)
在下图的右半部分,the color of f is special, its color the its original color + black,这句话的意思并不是给f涂了一层黑色,我们只是假设给他加了一层黑色。 算法在下次迭代的时候,对其颜色进行判断:
1、如果是黑色,并且不是root,现在他就是双黑节点,那么算法还是需要继续,
2、如果是黑色,并且他还是root节点,那么算法就结束了,此时的情形是,所有路径上的黑节点个数少了一个。
3、如果是红色节点,说明在这里可以弥补一个黑色节点,也就是将其染为黑色,这样做的作用有两个:首先左子树原先少的黑色节点被补充,同时右子树中黑色节点现在被弥补上(因为刚才被改称红色黑色节点)
假设情形三是从情形二转化而来的,那么此时新的开始节点一定为红色,所以算法结束。
情形四、当x为黑色的时候,w为黑色,w的左孩子为红色,右孩子为黑色。这是我们针对以w为根的子树进行一次右旋转。并且修改w的颜色为红色,w的左孩子颜色为黑色。这是转化为了情形五。
情形五、当x为黑色的时候,w为黑色,w的右孩子为红色,左孩子颜色随意。这种情况对一f为根的子树执行一次左旋转。并且修改w的颜色为红色,E的颜色为黑色。这是的左子树的黑节点增加了一个,算法结束。
复杂度分析:
case 1:over
case 2 ——> case 3 : over
case 2 ——> case 4 ——> case 5 : over
case 2 ——> case 5 : over
case 3: up
case 4 ——> case 5 : over
case 5 : over
所以在进入case1,case2,case 4,case 5之后算法很快就会结束,导致迭代的只能是case 3,所以复杂度为log(n)
posted on 2015-05-30 11:17 lightblueme 阅读(214) 评论(0) 编辑 收藏 举报