网站建设 网站开发 区别做网站开发需要什么技能
web/
2025/9/30 18:53:31/
文章来源:
网站建设 网站开发 区别,做网站开发需要什么技能,汇中建设 官方网站,低价网站设计2019独角兽企业重金招聘Python工程师标准 欢迎关注我的公众号“彤哥读源码”#xff0c;查看更多源码系列文章, 与彤哥一起畅游源码的海洋。 删除元素 删除元素本身比较简单#xff0c;就是采用二叉树的删除规则。 #xff08;1#xff09;如果删除的位置有两… 2019独角兽企业重金招聘Python工程师标准 欢迎关注我的公众号“彤哥读源码”查看更多源码系列文章, 与彤哥一起畅游源码的海洋。 删除元素 删除元素本身比较简单就是采用二叉树的删除规则。 1如果删除的位置有两个叶子节点则从其右子树中取最小的元素放到删除的位置然后把删除位置移到替代元素的位置进入下一步。 2如果删除的位置只有一个叶子节点有可能是经过第一步转换后的删除位置则把那个叶子节点作为替代元素放到删除的位置然后把这个叶子节点删除。 3如果删除的位置没有叶子节点则直接把这个删除位置的元素删除即可。 4针对红黑树如果删除位置是黑色节点还需要做再平衡。 5如果有替代元素则以替代元素作为当前节点进入再平衡。 6如果没有替代元素则以删除的位置的元素作为当前节点进入再平衡平衡之后再删除这个节点。 public V remove(Object key) {// 获取节点EntryK,V p getEntry(key);if (p null)return null;V oldValue p.value;// 删除节点deleteEntry(p);// 返回删除的valuereturn oldValue;
}private void deleteEntry(EntryK,V p) {// 修改次数加1modCount;// 元素个数减1size--;if (p.left ! null p.right ! null) {// 如果当前节点既有左子节点又有右子节点// 取其右子树中最小的节点EntryK,V s successor(p);// 用右子树中最小节点的值替换当前节点的值p.key s.key;p.value s.value;// 把右子树中最小节点设为当前节点p s;// 这种情况实际上并没有删除p节点而是把p节点的值改了实际删除的是p的后继节点}// 如果原来的当前节点p有2个子节点则当前节点已经变成原来p的右子树中的最小节点了也就是说其没有左子节点了// 到这一步p肯定只有一个子节点了// 如果当前节点有子节点则用子节点替换当前节点EntryK,V replacement (p.left ! null ? p.left : p.right);if (replacement ! null) {// 把替换节点直接放到当前节点的位置上相当于删除了p并把替换节点移动过来了replacement.parent p.parent;if (p.parent null)root replacement;else if (p p.parent.left)p.parent.left replacement;elsep.parent.right replacement;// 将p的各项属性都设为空p.left p.right p.parent null;// 如果p是黑节点则需要再平衡if (p.color BLACK)fixAfterDeletion(replacement);} else if (p.parent null) {// 如果当前节点就是根节点则直接将根节点设为空即可root null;} else {// 如果当前节点没有子节点且其为黑节点则把自己当作虚拟的替换节点进行再平衡if (p.color BLACK)fixAfterDeletion(p);// 平衡完成后删除当前节点与父节点断绝关系if (p.parent ! null) {if (p p.parent.left)p.parent.left null;else if (p p.parent.right)p.parent.right null;p.parent null;}}
}删除再平衡 经过上面的处理真正删除的肯定是黑色节点才会进入到再平衡阶段。 因为删除的是黑色节点导致整颗树不平衡了所以这里我们假设把删除的黑色赋予当前节点这样当前节点除了它自已的颜色还多了一个黑色那么 1如果当前节点是根节点则直接涂黑即可不需要再平衡 2如果当前节点是红黑节点则直接涂黑即可不需要平衡 3如果当前节点是黑黑节点则我们只要通过旋转把这个多出来的黑色不断的向上传递到一个红色节点即可这又可能会出现以下四种情况 假设当前节点为父节点的左子节点 情况策略1x是黑黑节点x的兄弟是红节点1将兄弟节点设为黑色br2将父节点设为红色br3以父节点为支点进行左旋br4重新设置x的兄弟节点进入下一步2x是黑黑节点x的兄弟是黑节点且兄弟节点的两个子节点都是黑色1将兄弟节点设置为红色br2将x的父节点作为新的当前节点进入下一次循环3x是黑黑节点x的兄弟是黑节点且兄弟节点的右子节点为黑色左子节点为红色1将兄弟节点的左子节点设为黑色br2将兄弟节点设为红色br3以兄弟节点为支点进行右旋br4重新设置x的兄弟节点进入下一步3x是黑黑节点x的兄弟是黑节点且兄弟节点的右子节点为红色左子节点任意颜色1将兄弟节点的颜色设为父节点的颜色br2将父节点设为黑色br3将兄弟节点的右子节点设为黑色br4以父节点为支点进行左旋br5将root作为新的当前节点退出循环假设当前节点为父节点的右子节点正好反过来 情况策略1x是黑黑节点x的兄弟是红节点1将兄弟节点设为黑色br2将父节点设为红色br3以父节点为支点进行右旋br4重新设置x的兄弟节点进入下一步2x是黑黑节点x的兄弟是黑节点且兄弟节点的两个子节点都是黑色1将兄弟节点设置为红色br2将x的父节点作为新的当前节点进入下一次循环3x是黑黑节点x的兄弟是黑节点且兄弟节点的左子节点为黑色右子节点为红色1将兄弟节点的右子节点设为黑色br2将兄弟节点设为红色br3以兄弟节点为支点进行左旋br4重新设置x的兄弟节点进入下一步3x是黑黑节点x的兄弟是黑节点且兄弟节点的左子节点为红色右子节点任意颜色1将兄弟节点的颜色设为父节点的颜色br2将父节点设为黑色br3将兄弟节点的左子节点设为黑色br4以父节点为支点进行右旋br5将root作为新的当前节点退出循环让我们来看看TreeMap中的实现 /*** 删除再平衡*1每个节点或者是黑色或者是红色。*2根节点是黑色。*3每个叶子节点NIL是黑色。注意这里叶子节点是指为空(NIL或NULL)的叶子节点*4如果一个节点是红色的则它的子节点必须是黑色的。*5从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。*/
private void fixAfterDeletion(EntryK,V x) {// 只有当前节点不是根节点且当前节点是黑色时才进入循环while (x ! root colorOf(x) BLACK) {if (x leftOf(parentOf(x))) {// 如果当前节点是其父节点的左子节点// sib是当前节点的兄弟节点EntryK,V sib rightOf(parentOf(x));// 情况1如果兄弟节点是红色if (colorOf(sib) RED) {// 1将兄弟节点设为黑色setColor(sib, BLACK);// 2将父节点设为红色setColor(parentOf(x), RED);// 3以父节点为支点进行左旋rotateLeft(parentOf(x));// 4重新设置x的兄弟节点进入下一步sib rightOf(parentOf(x));}if (colorOf(leftOf(sib)) BLACK colorOf(rightOf(sib)) BLACK) {// 情况2如果兄弟节点的两个子节点都是黑色// 1将兄弟节点设置为红色setColor(sib, RED);// 2将x的父节点作为新的当前节点进入下一次循环x parentOf(x);} else {if (colorOf(rightOf(sib)) BLACK) {// 情况3如果兄弟节点的右子节点为黑色// 1将兄弟节点的左子节点设为黑色setColor(leftOf(sib), BLACK);// 2将兄弟节点设为红色setColor(sib, RED);// 3以兄弟节点为支点进行右旋rotateRight(sib);// 4重新设置x的兄弟节点sib rightOf(parentOf(x));}// 情况4// 1将兄弟节点的颜色设为父节点的颜色setColor(sib, colorOf(parentOf(x)));// 2将父节点设为黑色setColor(parentOf(x), BLACK);// 3将兄弟节点的右子节点设为黑色setColor(rightOf(sib), BLACK);// 4以父节点为支点进行左旋rotateLeft(parentOf(x));// 5将root作为新的当前节点退出循环x root;}} else { // symmetric// 如果当前节点是其父节点的右子节点// sib是当前节点的兄弟节点EntryK,V sib leftOf(parentOf(x));// 情况1如果兄弟节点是红色if (colorOf(sib) RED) {// 1将兄弟节点设为黑色setColor(sib, BLACK);// 2将父节点设为红色setColor(parentOf(x), RED);// 3以父节点为支点进行右旋rotateRight(parentOf(x));// 4重新设置x的兄弟节点sib leftOf(parentOf(x));}if (colorOf(rightOf(sib)) BLACK colorOf(leftOf(sib)) BLACK) {// 情况2如果兄弟节点的两个子节点都是黑色// 1将兄弟节点设置为红色setColor(sib, RED);// 2将x的父节点作为新的当前节点进入下一次循环x parentOf(x);} else {if (colorOf(leftOf(sib)) BLACK) {// 情况3如果兄弟节点的左子节点为黑色// 1将兄弟节点的右子节点设为黑色setColor(rightOf(sib), BLACK);// 2将兄弟节点设为红色setColor(sib, RED);// 3以兄弟节点为支点进行左旋rotateLeft(sib);// 4重新设置x的兄弟节点sib leftOf(parentOf(x));}// 情况4// 1将兄弟节点的颜色设为父节点的颜色setColor(sib, colorOf(parentOf(x)));// 2将父节点设为黑色setColor(parentOf(x), BLACK);// 3将兄弟节点的左子节点设为黑色setColor(leftOf(sib), BLACK);// 4以父节点为支点进行右旋rotateRight(parentOf(x));// 5将root作为新的当前节点退出循环x root;}}}// 退出条件为多出来的黑色向上传递到了根节点或者红节点// 则将x设为黑色即可满足红黑树规则setColor(x, BLACK);
}删除元素举例 假设我们有下面这样一颗红黑树。 我们删除6号元素则从右子树中找到了最小元素77又没有子节点了所以把7作为当前节点进行再平衡。 我们看到7是黑节点且其兄弟为黑节点且其兄弟的两个子节点都是红色满足情况4平衡之后如下图所示。 我们再删除7号元素则从右子树中找到了最小元素88有子节点且为黑色所以8的子节点9是替代节点以9为当前节点进行再平衡。 我们发现9是红节点则直接把它涂成黑色即满足了红黑树的特性不需要再过多的平衡了。 这次我们来个狠的把根节点删除从右子树中找到了最小的元素55没有子节点所以把5作为当前节点进行再平衡。 我们看到5是黑节点且其兄弟为红色符合情况1平衡之后如下图所示然后进入情况2。 对情况2进行再平衡后如下图所示。 然后进入下一次循环发现不符合循环条件了直接把x涂为黑色即可退出这个方法之后会把旧x删除掉见deleteEntry()方法最后的结果就是下面这样。 未完待续下一节我们一起探讨红黑树遍历元素的操作。 现在公众号文章没办法留言了如果有什么疑问或者建议请直接在公众号给我留言。 欢迎关注我的公众号“彤哥读源码”查看更多源码系列文章, 与彤哥一起畅游源码的海洋。 转载于:https://my.oschina.net/u/4108008/blog/3032739
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84602.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!