本帖最后由 tonygone 于 2013-7-19 14:11 编辑
TreeMap删除元素:
和新增元素一样,删除元素也可能会破坏二叉树的平衡性,所以也可能需要做调整
假如当前要被删除节点有两个孩子节点,那么只需要将其后继节点查找出来,将其内容换成后继节点的内容,然后问题就转变成删除后继节点的问题.这里是找到当前节点的右子树中最小的那个节点的内容替代之,- Entry<K,V> p = t.right;
- while (p.left != null)
- p = p.left;
- return p;
复制代码 这样删除有两个孩子节点的节点问题就转换成删除带有一个子节点或者删除叶子节点的问题。接下来一段代码是:- // Start fixup at replacement node, if it exists.
- Entry<K,V> replacement = (p.left != null ? p.left : p.right);
复制代码 假如这里的p是上述后继节点得来,因为此时p不可能有左孩子,那替代者就是p.right,此时可能为null,或者是被删除节点的子节点少于两个的情况,可能是p.left,也可能是p.right.如果不是null的话就要将后继节点指向到p的parent节点,用于删除当前节点:- replacement.parent = p.parent;
- if (p.parent == null)
- root = replacement;
- else if (p == p.parent.left)
- p.parent.left = replacement;
- else
- p.parent.right = replacement;
复制代码 此时p被删除,假如p是红色的,那就不会影响红黑树,但是如果被删除的节点是黑色的,此时因为删掉了一个黑色节点,所以需要对原来的树进行调整:- while (x != root && colorOf(x) == BLACK) {
- if (x == leftOf(parentOf(x))) {//如果x是左子节点
- Entry<K,V> sib = rightOf(parentOf(x));
-
- if (colorOf(sib) == RED) {//如果其兄弟节点为红色
- setColor(sib, BLACK);//兄弟节点设为黑色
- setColor(parentOf(x), RED);//父节点设置为红色
- rotateLeft(parentOf(x));//父节点左旋
- sib = rightOf(parentOf(x));
- }
-
- if (colorOf(leftOf(sib)) == BLACK &&
- colorOf(rightOf(sib)) == BLACK) {//如果兄弟节点的两个儿子都是黑色
- setColor(sib, RED);//兄弟节点设置为红色
- x = parentOf(x);
- } else {
- if (colorOf(rightOf(sib)) == BLACK) {
- setColor(leftOf(sib), BLACK);
- setColor(sib, RED);
- rotateRight(sib);
- sib = rightOf(parentOf(x));
- }
- setColor(sib, colorOf(parentOf(x)));
- setColor(parentOf(x), BLACK);
- setColor(rightOf(sib), BLACK);
- rotateLeft(parentOf(x));
- x = root;
- }
- }
- setColor(x, BLACK);
复制代码 另外,如果replacement值是空的,就说明被删除节点没有子节点,如果是黑色节点需要进行调整再删除,如果不是就直接删除即可- 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;
- }
复制代码 |