[Joafip-svn] SF.net SVN: joafip:[3170] trunk/joafip-rbtree
Brought to you by:
luc_peuvrier
From: <luc...@us...> - 2012-11-28 12:17:52
|
Revision: 3170 http://joafip.svn.sourceforge.net/joafip/?rev=3170&view=rev Author: luc_peuvrier Date: 2012-11-28 12:17:40 +0000 (Wed, 28 Nov 2012) Log Message: ----------- red black tree management changed. foreground garbage sweep changed Modified Paths: -------------- trunk/joafip-rbtree/pom.xml trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/impl/memory/entity/RBTNode.java trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RedBlackTree.java trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestByPosition.java trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestDelete.java trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestInsert.java trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/TreeShower.java Added Paths: ----------- trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RBTRuntimeException.java Modified: trunk/joafip-rbtree/pom.xml =================================================================== --- trunk/joafip-rbtree/pom.xml 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/pom.xml 2012-11-28 12:17:40 UTC (rev 3170) @@ -25,6 +25,13 @@ <dependency> <groupId>net.sf.joafip</groupId> + <artifactId>joafip-common</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + + <dependency> + <groupId>net.sf.joafip</groupId> <artifactId>joafip-log4j</artifactId> <scope>test</scope> </dependency> Modified: trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/impl/memory/entity/RBTNode.java =================================================================== --- trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/impl/memory/entity/RBTNode.java 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/impl/memory/entity/RBTNode.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -25,6 +25,7 @@ import net.sf.joafip.redblacktree.entity.IRBTNode; import net.sf.joafip.redblacktree.service.IRBTVisitor; import net.sf.joafip.redblacktree.service.RBTException; +import net.sf.joafip.redblacktree.service.RBTRuntimeException; import net.sf.joafip.redblacktree.service.RedBlackTree; import net.sf.joafip.store.service.proxy.IInstanceFactory; @@ -357,14 +358,29 @@ visitor.endVisit(this); } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public boolean equals(final Object obj) { - throw new UnsupportedOperationException(); + final boolean equals; + if (obj == null) { + equals = false; + } else if (obj == this) { + equals = true; + } else if (obj instanceof RBTNode) { + try { + equals = compareTo((IRBTComparableNode) obj) == 0; + } catch (RBTException exception) { + throw new RBTRuntimeException(exception); + } + } else { + equals = false; + } + return equals; } @Override public int hashCode() { - throw new UnsupportedOperationException(); + return element == null ? 0 : element.hashCode(); } @Override Added: trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RBTRuntimeException.java =================================================================== --- trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RBTRuntimeException.java (rev 0) +++ trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RBTRuntimeException.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -0,0 +1,45 @@ +/* + * Copyright 2012 Luc Peuvrier + * + * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE + * Licensed under the LGPL License, Version 3, 29 June 2007 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.gnu.org/licenses/lgpl.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.joafip.redblacktree.service; + +import net.sf.joafip.NotStorableClass; + +@NotStorableClass +public class RBTRuntimeException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 7478871706595989215L; + + public RBTRuntimeException() { + super(); + } + + public RBTRuntimeException(final String message, final Throwable cause) { + super(message, cause); + } + + public RBTRuntimeException(final String message) { + super(message); + } + + public RBTRuntimeException(final Throwable cause) { + super(cause); + } + +} Property changes on: trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RBTRuntimeException.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RedBlackTree.java =================================================================== --- trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RedBlackTree.java 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/src/main/java/net/sf/joafip/redblacktree/service/RedBlackTree.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -23,6 +23,7 @@ import net.sf.joafip.AssertNotNull; import net.sf.joafip.StorableClass; import net.sf.joafip.StoreNotUseStandardSerialization; +import net.sf.joafip.logger.JoafipLogger; import net.sf.joafip.redblacktree.entity.IRBTNode; import net.sf.joafip.store.service.proxy.IInstanceFactory; @@ -46,6 +47,9 @@ // complexity Iterable<IRBTNode<E>>, Serializable { + private static final JoafipLogger LOGGER = JoafipLogger + .getLogger(RedBlackTree.class); + private static final String MAX_DEPTH_REACHED = "max depth reached"; /** @@ -1003,7 +1007,8 @@ incrementNumberOfChild(parent); } // Rebalance after insert. - insertReorganize(nodeToAppend); + // insertReorganize(nodeToAppend); + insertionReorganize(nodeToAppend); } } @@ -1117,96 +1122,129 @@ * * @param nodeToDelete * node to delete + * @return * @throws RBTException * node access error */ - private void privateDeleteExistingNode(final IRBTNode<E> nodeToDelete)// NOPMD + private IRBTNode<E> privateDeleteExistingNode(final IRBTNode<E> nodeToDelete)// NOPMD // complexity // ok throws RBTException { - if (!manageNodeIndex) { final int numberOfElement = getNumberOfElementInternal(); rootNumberOfChild = numberOfElement - 1; } - IRBTNode<E> node = nodeToDelete; - IRBTNode<E> substitute; - final IRBTNode<E> child; - // search for substitute to the node to delete - if (node.getLeft().isSentinel()) { - // the node to be deleted has 0 or 1 child - substitute = node; - child = node.getRight(); - } else if (node.getRight().isSentinel()) { - // the node to be deleted has 1 child - substitute = node; - child = node.getLeft(); - } else { - /* - * the node to delete has 2 or more children. substitute is - * predecessor of the node to delete. - */ - substitute = node.getLeft(); - int depth = 0; - while (!substitute.getRight().isSentinel()) { - substitute = substitute.getRight(); - if (++depth == MAX_DEPTH) { - throw new RBTException(MAX_DEPTH_REACHED); - } - } + // If strictly internal, copy successor's element to p and then make p + // point to successor. + // if p has 2 children + if (!nodeToDelete.getLeft().isSentinel() + && !nodeToDelete.getRight().isSentinel()) { + final IRBTNode<E> successor = successor(nodeToDelete); + swap(nodeToDelete, successor); + } - child = substitute.getLeft(); + // Start fixup at replacement node, if it exists. + final IRBTNode<E> replacement = (!nodeToDelete.getLeft().isSentinel() ? nodeToDelete + .getLeft() : nodeToDelete.getRight()); - // swap the substitute and node to delete - swap(node, substitute); - final IRBTNode<E> tmp = node; - node = substitute; - substitute = tmp; + if (manageNodeIndex) { + decrementNumberOfChild(nodeToDelete); } - /* - * Unlink substitute from the tree ( substitute became the real node to - * detach to the tree). - */ - final IRBTNode<E> parent = substitute.getParent(); - child.setParent(parent); - if (parent == null) { - // 0 or 1 node remaining. - if (child.isSentinel()) { - rootNode = null;// NOPMD + IRBTNode<E> parentOfNodeToDelete = nodeToDelete.getParent(); + if (!replacement.isSentinel()) { + // Link replacement to parent + replacement.setParent(parentOfNodeToDelete); + if (parentOfNodeToDelete == null) { + rootNode = replacement; + } else if (nodeToDelete == parentOfNodeToDelete.getLeft()) { + parentOfNodeToDelete.setLeft(replacement); } else { - child.setBlack(); - rootNode = child; - child.setNumberOfChild(0); + parentOfNodeToDelete.setRight(replacement); } - /* detach the node to the tree */ - node.detach(); + // Null out links so they are OK to use by fixAfterDeletion. + // FIXMELUC __________________________see detach + nodeToDelete.setParent(null); + IRBTNode<E> newSentinel = nodeManager.newSentinel(); + nodeToDelete.setLeft(newSentinel); + newSentinel.setParent(nodeToDelete); + newSentinel = nodeManager.newSentinel(); + nodeToDelete.setRight(newSentinel); + newSentinel.setParent(nodeToDelete); + + // Fix replacement + if (nodeToDelete.getColor() == BLACK) { + deletionReorganize(replacement); + } + } else if (parentOfNodeToDelete == null) { + // return if it is the only node. + rootNode = null; } else { - if (substitute == parent.getLeft()) { - parent.setLeft(child); - } else { - parent.setRight(child); + // No children. Use self as phantom replacement and unlink. + if (nodeToDelete.getColor() == BLACK) { + deletionReorganize(nodeToDelete); + parentOfNodeToDelete = nodeToDelete.getParent(); } - if (manageNodeIndex) { - decrementNumberOfChild(parent); - } - if (substitute.isBlack()) { - deleteReorganize(child, parent); + if (parentOfNodeToDelete != null) { + IRBTNode<E> newSentinel = nodeManager.newSentinel(); + if (nodeToDelete == parentOfNodeToDelete.getLeft()) { + parentOfNodeToDelete.setLeft(newSentinel); + } else { + parentOfNodeToDelete.setRight(newSentinel); + } + newSentinel.setParent(parentOfNodeToDelete); + // FIXMELUC __________________________see detach + nodeToDelete.setParent(null); } - - /* detach the node to the tree */ - substitute.detach(); } - // assertNotAttached(nodeToDelete); + nodeToDelete.detach(); if (!manageNodeIndex && rootNumberOfChild != 0) { rootNode.setNumberOfChild(rootNumberOfChild - 1); } + return nodeToDelete; } /** - * swap to node, the node instance and state are swaped.make able to swap + * Returns the successor of the specified Entry, or null if no such. + * + * @throws RBTException + */ + private static <E> IRBTNode<E> successor(final IRBTNode<E> node) + throws RBTException { + if (node == null) { + return null; + // } else if (t.right != null) { + } else if (!node.getRight().isSentinel()) { + IRBTNode<E> successor = node.getRight(); + // while (p.left != null) + int depth = 0; + while (!successor.getLeft().isSentinel()) { + successor = successor.getLeft(); + if (++depth == MAX_DEPTH) { + throw new RBTException(MAX_DEPTH_REACHED); + } + } + return successor; + } else { + IRBTNode<E> successor = node.getParent(); + IRBTNode<E> child = node; + // while (p != null && ch == p.right) { + int depth = 0; + while (successor != null && child == successor.getRight()) { + child = successor; + successor = successor.getParent(); + if (++depth == MAX_DEPTH) { + throw new RBTException(MAX_DEPTH_REACHED); + } + } + return successor; + } + } + + /** + * swap two node, the node instance and state are swaped.make able to swap * node without acceding to its stored elements ( real implementation ) * * @param node @@ -1219,44 +1257,41 @@ private void swap(final IRBTNode<E> node, final IRBTNode<E> subsititute) throws RBTException { - IRBTNode<E> tmp; + final IRBTNode<E> parentOfSubstitute = subsititute.getParent(); + final IRBTNode<E> parentOfNode = node.getParent(); - tmp = node.getParent(); - final IRBTNode<E> parent = subsititute.getParent(); - - subsititute.setParent(tmp); - if (tmp == null) { + subsititute.setParent(parentOfNode); + if (parentOfNode == null) { rootNode = subsititute; - } else if (tmp.getLeft() == node) { - tmp.setLeft(subsititute); + } else if (parentOfNode.getLeft() == node) { + parentOfNode.setLeft(subsititute); } else { - tmp.setRight(subsititute); + parentOfNode.setRight(subsititute); } - if (parent == node) {// NOPMD compare instance - - node.setParent(subsititute); - node.setLeft(subsititute.getLeft()); - subsititute.getLeft().setParent(node); - subsititute.setLeft(node); - + node.setParent(parentOfSubstitute); + if (parentOfSubstitute == null) { + rootNode = node; + } else if (parentOfSubstitute.getLeft() == subsititute) { + parentOfSubstitute.setLeft(node); } else { - node.setParent(parent); - parent.setRight(node); - - tmp = subsititute.getLeft(); - subsititute.setLeft(node.getLeft()); - node.getLeft().setParent(subsititute); - node.setLeft(tmp); - tmp.setParent(node); + parentOfSubstitute.setRight(node); } - tmp = subsititute.getRight(); - subsititute.setRight(node.getRight()); - node.getRight().setParent(subsititute); - node.setRight(tmp); - tmp.setParent(node); + final IRBTNode<E> leftOfSubsititute = subsititute.getLeft(); + final IRBTNode<E> leftOfNode = node.getLeft(); + subsititute.setLeft(leftOfNode); + leftOfNode.setParent(subsititute); + node.setLeft(leftOfSubsititute); + leftOfSubsititute.setParent(node); + final IRBTNode<E> rightOfSubstitute = subsititute.getRight(); + final IRBTNode<E> rightOfNode = node.getRight(); + subsititute.setRight(rightOfNode); + rightOfNode.setParent(subsititute); + node.setRight(rightOfSubstitute); + rightOfSubstitute.setParent(node); + final boolean color = node.getColor(); node.setColor(subsititute.getColor()); subsititute.setColor(color); @@ -1531,194 +1566,135 @@ return currentNode; } - /** - * rebalance this red-black tree after inserting a new node. - * - * @param n - * the inserted node - * @throws RBTException - * node access error - */ - private void insertReorganize(final IRBTNode<E> node)// NOPMD complexity - // ok + private void insertionReorganize(final IRBTNode<E> node) throws RBTException { - // Only need to rebalance when parent is a RED node, and while at least - // 2 levels deep into the tree (ie: node has a grandparent). Remember - // that nil.color == BLACK. - IRBTNode<E> currentNode = node; - IRBTNode<E> currentNodeParent = currentNode.getParent(); - IRBTNode<E> currentNodeParentParent; - int depth = 0; - while (currentNodeParent != null // NOPMD - && currentNodeParent.isRed() - && (currentNodeParentParent = currentNodeParent.getParent()) != null) { - if (currentNodeParent == currentNodeParentParent.getLeft()) { - final IRBTNode<E> uncle = currentNodeParentParent.getRight(); - // Uncle may be nil, in which case it is BLACK. - if (uncle.isRed()) { - // Case 1. Uncle is RED: Change colors of parent, uncle, - // and grandparent, and move n to grandparent. - currentNodeParent.setBlack(); - uncle.setBlack(); - uncle.getParent().setRed(); - currentNode = uncle.getParent(); - currentNodeParent = currentNode.getParent(); + IRBTNode<E> x = node; + x.setColor(RED); + IRBTNode<E> parentOfX = x.getParent(); + IRBTNode<E> parentOfParentOfX = parentOf(parentOfX); + while (x != null && x != rootNode && parentOfX.getColor() == RED) { + if (parentOf(x) == leftOf(parentOfParentOfX)) { + IRBTNode<E> y = rightOf(parentOfParentOfX); + if (colorOf(y) == RED) { + setColor(parentOfX, BLACK); + setColor(y, BLACK); + setColor(parentOfParentOfX, RED); + x = parentOfParentOfX; + // x parent + parentOfX = parentOf(x); + parentOfParentOfX = parentOf(parentOfX); } else { - if (currentNode == currentNodeParent.getRight()) { - // Case 2. Uncle is BLACK and x is right child. - // Move n to parent, and rotate n left. - currentNode = currentNodeParent; - // rotateLeft(n); - leftRotation(currentNode); - currentNodeParent = currentNode.getParent(); + if (x == rightOf(parentOfX)) { + x = parentOfX; + leftRotation(x); + // x parent + parentOfX = parentOf(x); + parentOfParentOfX = parentOf(parentOfX); } - // Case 3. Uncle is BLACK and x is left child. - // Recolor parent, grandparent, and rotate grandparent - // right. - currentNodeParent.setBlack(); - currentNodeParentParent = currentNodeParent.getParent(); - currentNodeParentParent.setRed(); - rightRotation(currentNodeParentParent); + setColor(parentOfX, BLACK); + setColor(parentOfParentOfX, RED); + rightRotation(parentOfParentOfX); + // x parent + parentOfX = parentOf(x); + parentOfParentOfX = parentOf(parentOfX); } } else { - // Mirror image of above code. - final IRBTNode<E> uncle = currentNodeParentParent.getLeft(); - // Uncle may be nil, in which case it is BLACK. - if (uncle.isRed()) { - // Case 1. Uncle is RED: Change colors of parent, uncle, - // and grandparent, and move n to grandparent. - currentNodeParent.setBlack(); - uncle.setBlack(); - uncle.getParent().setRed(); - currentNode = uncle.getParent(); - currentNodeParent = currentNode.getParent(); + IRBTNode<E> y = leftOf(parentOfParentOfX); + if (colorOf(y) == RED) { + setColor(parentOfX, BLACK); + setColor(y, BLACK); + setColor(parentOfParentOfX, RED); + x = parentOfParentOfX; + // x parent + parentOfX = parentOf(x); + parentOfParentOfX = parentOf(parentOfX); + } else { - if (currentNode == currentNodeParent.getLeft()) { - // Case 2. Uncle is BLACK and x is left child. - // Move n to parent, and rotate n right. - currentNode = currentNodeParent; - // rotateRight(n); - rightRotation(currentNode); - currentNodeParent = currentNode.getParent(); + if (x == leftOf(parentOfX)) { + x = parentOfX; + rightRotation(x); + // x parent + parentOfX = parentOf(x); + parentOfParentOfX = parentOf(parentOfX); + } - // Case 3. Uncle is BLACK and x is right child. - // Recolor parent, grandparent, and rotate grandparent left. - currentNodeParent.setBlack(); - currentNodeParentParent = currentNodeParent.getParent(); - currentNodeParentParent.setRed(); - leftRotation(currentNodeParentParent); + setColor(parentOfX, BLACK); + setColor(parentOfParentOfX, RED); + leftRotation(parentOfParentOfX); + // x parent + parentOfX = parentOf(x); + parentOfParentOfX = parentOf(parentOfX); } } - if (++depth == MAX_DEPTH) { - throw new RBTException(MAX_DEPTH_REACHED); - } } - rootNode.setBlack(); + rootNode.setColor(BLACK); } - /** - * rebalance this red-black tree after deleting a node. - * - * @param node - * the child of the node deleted, possibly sentinel - * @param parent - * the parent of the node deleted, never sentinel or null - * @throws RBTException - * node access error - */ - private void deleteReorganize(// NOPMD complexity ok - final IRBTNode<E> childNode, final IRBTNode<E> parentNode) - throws RBTException { - // ASSERTX - assert parentNode != null && !parentNode.isSentinel() : "parent node can not be null nor sentinel"; - IRBTNode<E> node = childNode; - IRBTNode<E> parent = parentNode; - int depth = 0; - while (node != rootNode && node.isBlack()) {// NOPMD - if (node == parent.getLeft()) { - // Rebalance left side. - IRBTNode<E> sibling = parent.getRight(); - if (sibling.isRed()) { - // Case 1: Sibling is red. - // Recolor sibling and parent, and rotate parent left. - sibling.setBlack(); - parent.setRed(); - // rotateLeft(parent); - leftRotation(parent); - sibling = parent.getRight(); + private void deletionReorganize(IRBTNode<E> x) throws RBTException { + while (x != rootNode && colorOf(x) == BLACK) { + IRBTNode<E> parentOfX = parentOf(x); + if (x == leftOf(parentOfX)) { + IRBTNode<E> sib = rightOf(parentOfX); + + if (colorOf(sib) == RED) { + setColor(sib, BLACK); + setColor(parentOfX, RED); + leftRotation(parentOfX); + parentOfX = parentOf(x); + sib = rightOf(parentOfX); } - final IRBTNode<E> left = sibling.getLeft(); - final IRBTNode<E> right = sibling.getRight(); - if (left.isBlack() && right.isBlack()) { - // Case 2: Sibling has no red children. - // Recolor sibling, and move to parent. - sibling.setRed(); - node = parent; - parent = parent.getParent(); + if (colorOf(leftOf(sib)) == BLACK + && colorOf(rightOf(sib)) == BLACK) { + setColor(sib, RED); + x = parentOfX; } else { - if (right.isBlack()) { - // Case 3: Sibling has red left child. - // Recolor sibling and left child, rotate sibling right. - left.setBlack(); - sibling.setRed(); - // rotateRight(sibling); - rightRotation(sibling); - sibling = parent.getRight(); + if (colorOf(rightOf(sib)) == BLACK) { + setColor(leftOf(sib), BLACK); + setColor(sib, RED); + rightRotation(sib); + parentOfX = parentOf(x); + sib = rightOf(parentOfX); } - // Case 4: Sibling has red right child. Recolor sibling, - // right child, and parent, and rotate parent left. - sibling.setColor(parent.getColor()); - parent.setBlack(); - sibling.getRight().setBlack(); - // rotateLeft(parent); - leftRotation(parent); - node = rootNode; // Finished. + setColor(sib, colorOf(parentOfX)); + setColor(parentOfX, BLACK); + setColor(rightOf(sib), BLACK); + leftRotation(parentOfX); + x = rootNode; } - } else { - // Symmetric "mirror" of left-side case. - IRBTNode<E> sibling = parent.getLeft(); - if (sibling.isRed()) { - // Case 1: Sibling is red. - // Recolor sibling and parent, and rotate parent right. - sibling.setBlack(); - parent.setRed(); - rightRotation(parent); - sibling = parent.getLeft(); + } else { // symmetric + IRBTNode<E> sib = leftOf(parentOfX); + + if (colorOf(sib) == RED) { + setColor(sib, BLACK); + setColor(parentOfX, RED); + rightRotation(parentOfX); + parentOfX = parentOf(x); + sib = leftOf(parentOfX); } - final IRBTNode<E> left = sibling.getLeft(); - final IRBTNode<E> right = sibling.getRight(); - if (right.isBlack() && left.isBlack()) { - // Case 2: Sibling has no red children. - // Recolor sibling, and move to parent. - sibling.setRed(); - node = parent; - parent = parent.getParent(); + if (colorOf(rightOf(sib)) == BLACK + && colorOf(leftOf(sib)) == BLACK) { + setColor(sib, RED); + x = parentOfX; } else { - if (left.isBlack()) { - // Case 3: Sibling has red right child. - // Recolor sibling and right child, rotate sibling left. - right.setBlack(); - sibling.setRed(); - // rotateLeft(sibling); - leftRotation(sibling); - sibling = parent.getLeft(); + if (colorOf(leftOf(sib)) == BLACK) { + setColor(rightOf(sib), BLACK); + setColor(sib, RED); + leftRotation(sib); + parentOfX = parentOf(x); + sib = leftOf(parentOfX); } - // Case 4: Sibling has red left child. Recolor sibling, - // left child, and parent, and rotate parent right. - sibling.setColor(parent.getColor()); - parent.setBlack(); - sibling.getLeft().setBlack(); - rightRotation(parent); - node = rootNode; // Finished. + setColor(sib, colorOf(parentOfX)); + setColor(parentOf(x), BLACK); + setColor(leftOf(sib), BLACK); + rightRotation(parentOfX); + x = rootNode; } } - if (++depth == MAX_DEPTH) { - throw new RBTException(MAX_DEPTH_REACHED); - } } - node.setBlack(); + + setColor(x, BLACK); } private void leftRotation(final IRBTNode<E> node) throws RBTException { @@ -1775,15 +1751,29 @@ } } - private IRBTNode<E> parentOf(final IRBTNode<E> node) throws RBTException { + private static <E> boolean colorOf(IRBTNode<E> p) throws RBTException { + return (p == null ? BLACK : p.getColor()); + } + + private static <E> void setColor(IRBTNode<E> p, boolean c) + throws RBTException { + if (p != null) { + p.setColor(c); + } + } + + private static <E> IRBTNode<E> parentOf(final IRBTNode<E> node) + throws RBTException { return (node == null ? null : node.getParent()); } - private IRBTNode<E> leftOf(final IRBTNode<E> node) throws RBTException { + private static <E> IRBTNode<E> leftOf(final IRBTNode<E> node) + throws RBTException { return (node == null || node.isSentinel()) ? null : node.getLeft();// NOPMD } - private IRBTNode<E> rightOf(final IRBTNode<E> node) throws RBTException { + private static <E> IRBTNode<E> rightOf(final IRBTNode<E> node) + throws RBTException { return (node == null || node.isSentinel()) ? null : node.getRight();// NOPMD } @@ -1821,7 +1811,7 @@ * the starting node having a new child * @throws RBTException */ - private void incrementNumberOfChild(final IRBTNode<E> node) + private static <E> void incrementNumberOfChild(final IRBTNode<E> node) throws RBTException { IRBTNode<E> current = node; int depth = 0; @@ -1834,7 +1824,7 @@ } } - private void decrementNumberOfChild(final IRBTNode<E> node) + private static <E> void decrementNumberOfChild(final IRBTNode<E> node) throws RBTException { IRBTNode<E> current = node; int depth = 0; @@ -1847,7 +1837,7 @@ } } - private void updateNumberOfChild(final IRBTNode<E> node) + private static <E> void updateNumberOfChild(final IRBTNode<E> node) throws RBTException { final IRBTNode<E> left = node.getLeft(); final IRBTNode<E> right = node.getRight(); @@ -1880,6 +1870,11 @@ throw new RBTException(MAX_DEPTH_REACHED); } } - return current == nodeManager.getRootNode(); + final boolean attached = current == nodeManager.getRootNode(); + if (!attached) { + LOGGER.error("current is: " + current.toString() + "\nroot is: " + + nodeManager.getRootNode().toString()); + } + return attached; } } Modified: trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestByPosition.java =================================================================== --- trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestByPosition.java 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestByPosition.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -96,6 +96,8 @@ /**/new RBTNode<Integer>(beforeList[index]);// NOPMD tree.appendAfterLast(node); } + assertEquals("bad number of element", 6, tree.getNumberOfElement()); + IRBTNode<Integer> deleted = tree.deleteByIndex(2); assertEquals("bad element", Integer.valueOf(10), deleted.getElement()); deleted = tree.deleteByIndex(4); Modified: trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestDelete.java =================================================================== --- trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestDelete.java 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestDelete.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -21,6 +21,7 @@ import net.sf.joafip.NotStorableClass; import net.sf.joafip.TestException; import net.sf.joafip.logger.JoafipLogger; +import net.sf.joafip.redblacktree.entity.IRBTNode; import net.sf.joafip.redblacktree.impl.memory.entity.RBTNode; import net.sf.joafip.redblacktree.impl.memory.service.RBTNodeManager; @@ -28,10 +29,10 @@ @DoNotTransform public abstract class AbstractTestDelete extends AbstractJoafipCommonTestCase { + private static final String BAD_NUMBER_OF_ELEMENT = "bad number of element"; + protected final JoafipLogger logger = JoafipLogger.getLogger(getClass()); - private final static TreeShower SHOWER = TreeShower.getInstance(); - class IntHolder implements Comparable<IntHolder> { private final int value; @@ -85,6 +86,17 @@ return false; return true; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("IntHolder [value="); + builder.append(value); + builder.append(", identifier="); + builder.append(identifier); + builder.append("]"); + return builder.toString(); + } } protected RedBlackTree<IntHolder> redBlackTree; @@ -114,18 +126,28 @@ public void testDelete1() throws RBTException {// NOPMD assert in method // called + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); final RBTNode<IntHolder> node = new RBTNode<IntHolder>(new IntHolder(0)); checker.checkTree(); redBlackTree.append(node); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 1, + redBlackTree.getNumberOfElement()); + //TreeShower treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); redBlackTree.delete(new IntHolder(0)); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); + //treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); } public void testDelete2() throws RBTException {// NOPMD assert in method // called + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); checker.checkTree(); final RBTNode<IntHolder> node0 = new RBTNode<IntHolder>( new IntHolder(0)); @@ -133,20 +155,31 @@ final RBTNode<IntHolder> node1 = new RBTNode<IntHolder>( new IntHolder(1)); redBlackTree.append(node1); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 2, + redBlackTree.getNumberOfElement()); + //TreeShower treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); redBlackTree.delete(new IntHolder(0)); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 1, + redBlackTree.getNumberOfElement()); + //treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); redBlackTree.delete(new IntHolder(1)); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); + //treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); } public void testDelete3() throws RBTException {// NOPMD assert in method // called + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); checker.checkTree(); final RBTNode<IntHolder> node0 = new RBTNode<IntHolder>( new IntHolder(0)); @@ -154,16 +187,23 @@ final RBTNode<IntHolder> node1 = new RBTNode<IntHolder>( new IntHolder(1)); redBlackTree.append(node1); + assertEquals(BAD_NUMBER_OF_ELEMENT, 2, + redBlackTree.getNumberOfElement()); checker.checkTree(); redBlackTree.delete(new IntHolder(1)); + assertEquals(BAD_NUMBER_OF_ELEMENT, 1, + redBlackTree.getNumberOfElement()); checker.checkTree(); redBlackTree.delete(new IntHolder(0)); + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); checker.checkTree(); } public void testDelete4() throws RBTException {// NOPMD assert in method // called - final TreeShower shower = TreeShower.getInstance(); + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); checker.checkTree(); final RBTNode<IntHolder> node0 = new RBTNode<IntHolder>( new IntHolder(0)); @@ -174,18 +214,28 @@ final RBTNode<IntHolder> node2 = new RBTNode<IntHolder>( new IntHolder(2)); redBlackTree.append(node2); - shower.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 3, + redBlackTree.getNumberOfElement()); + //TreeShower treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); redBlackTree.delete(new IntHolder(1)); - shower.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 2, + redBlackTree.getNumberOfElement()); + //treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); redBlackTree.delete(new IntHolder(2)); + assertEquals(BAD_NUMBER_OF_ELEMENT, 1, + redBlackTree.getNumberOfElement()); checker.checkTree(); } public void testDelete5() throws RBTException {// NOPMD assert in method // called + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); final RBTNode<IntHolder> node0 = new RBTNode<IntHolder>( new IntHolder(0)); redBlackTree.append(node0); @@ -198,14 +248,21 @@ final RBTNode<IntHolder> node3 = new RBTNode<IntHolder>( new IntHolder(3)); redBlackTree.append(node3); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 4, + redBlackTree.getNumberOfElement()); + //TreeShower treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); redBlackTree.deleteExistingNode(node1); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 3, + redBlackTree.getNumberOfElement()); + //treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); } + @SuppressWarnings("unchecked") public void testDelete6() throws RBTException {// NOPMD assert in method // called final RBTNode<IntHolder> node0 = new RBTNode<IntHolder>( @@ -244,14 +301,96 @@ final RBTNode<IntHolder> node11 = new RBTNode<IntHolder>(new IntHolder( 11)); redBlackTree.append(node11); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 12, + redBlackTree.getNumberOfElement()); + //TreeShower treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); - + search(redBlackTree,new RBTNode[]{node0,node1,node2,node3,node4,node5,node6,node7,node8,node9,node10,node11}); + redBlackTree.deleteExistingNode(node5); - SHOWER.show(redBlackTree); + assertEquals(BAD_NUMBER_OF_ELEMENT, 11, + redBlackTree.getNumberOfElement()); + //treeShower = new TreeShower(); + //treeShower.show(redBlackTree); checker.checkTree(); + search(redBlackTree,new RBTNode[]{node0,node1,node2,node3,node4,node6,node7,node8,node9,node10,node11}); + + redBlackTree.deleteExistingNode(node2); + assertEquals(BAD_NUMBER_OF_ELEMENT, 10, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node0,node1,node3,node4,node6,node7,node8,node9,node10,node11}); + + redBlackTree.deleteExistingNode(node8); + assertEquals(BAD_NUMBER_OF_ELEMENT, 9, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node0,node1,node3,node4,node6,node7,node9,node10,node11}); + + redBlackTree.deleteExistingNode(node3); + assertEquals(BAD_NUMBER_OF_ELEMENT, 8, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node0,node1,node4,node6,node7,node9,node10,node11}); + + redBlackTree.deleteExistingNode(node10); + assertEquals(BAD_NUMBER_OF_ELEMENT, 7, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node0,node1,node4,node6,node7,node9,node11}); + + redBlackTree.deleteExistingNode(node0); + assertEquals(BAD_NUMBER_OF_ELEMENT, 6, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node1,node4,node6,node7,node9,node11}); + + redBlackTree.deleteExistingNode(node7); + assertEquals(BAD_NUMBER_OF_ELEMENT, 5, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node1,node4,node6,node9,node11}); + + redBlackTree.deleteExistingNode(node1); + assertEquals(BAD_NUMBER_OF_ELEMENT, 4, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node4,node6,node9,node11}); + + redBlackTree.deleteExistingNode(node9); + assertEquals(BAD_NUMBER_OF_ELEMENT, 3, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node4,node6,node11}); + + redBlackTree.deleteExistingNode(node4); + assertEquals(BAD_NUMBER_OF_ELEMENT, 2, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node6,node11}); + + redBlackTree.deleteExistingNode(node6); + assertEquals(BAD_NUMBER_OF_ELEMENT, 1, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + search(redBlackTree,new RBTNode[]{node11}); + + redBlackTree.deleteExistingNode(node11); + assertEquals(BAD_NUMBER_OF_ELEMENT, 0, + redBlackTree.getNumberOfElement()); + checker.checkTree(); + } + private void search(final RedBlackTree<IntHolder> redBlackTree, + final RBTNode<IntHolder>[] rbtNodes) throws RBTException { + for(RBTNode<IntHolder> rbtNode:rbtNodes){ + IRBTNode<IntHolder> found = redBlackTree.search(rbtNode.getElement()); + assertSame("must found same node",rbtNode,found); + } + } + public void testDeleteRoot() throws RBTException {// NOPMD assert in // method called final RBTNode<IntHolder> root = new RBTNode<IntHolder>(new IntHolder(2)); @@ -260,8 +399,8 @@ redBlackTree.append(node); node = new RBTNode<IntHolder>(new IntHolder(3)); redBlackTree.append(node); - final TreeShower showTree = TreeShower.getInstance(); - showTree.show(redBlackTree); + //final TreeShower showTree = new TreeShower(); + //showTree.show(redBlackTree); redBlackTree.delete(new IntHolder(2)); } @@ -271,6 +410,8 @@ for (int value = 0; value < 1024; value++) { assertTrue("missing value " + value, redBlackTree.delete(new IntHolder(value)));// NOPMD + assertEquals(BAD_NUMBER_OF_ELEMENT, 1023 - value, + redBlackTree.getNumberOfElement()); try { checker.checkTree(); } catch (RBTException exception) { @@ -291,6 +432,8 @@ final RBTNode<IntHolder> node = /**/new RBTNode<IntHolder>(new IntHolder(function(value)));// NOPMD redBlackTree.append(node); + assertEquals(BAD_NUMBER_OF_ELEMENT, value + 1, + redBlackTree.getNumberOfElement()); } } Modified: trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestInsert.java =================================================================== --- trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestInsert.java 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/AbstractTestInsert.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -54,7 +54,7 @@ redBlackTree = new RedBlackTree<String>(nodeManager, false, uniqueValue()); checker = new RedBlackTreeIntegrityChecker<String>(redBlackTree); - shower = TreeShower.getInstance(); + shower = new TreeShower(); super.setUp(); } Modified: trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/TreeShower.java =================================================================== --- trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/TreeShower.java 2012-11-28 12:17:20 UTC (rev 3169) +++ trunk/joafip-rbtree/src/test/java/net/sf/joafip/redblacktree/service/TreeShower.java 2012-11-28 12:17:40 UTC (rev 3170) @@ -30,69 +30,68 @@ */ @SuppressWarnings("rawtypes") @NotStorableClass -public final class TreeShower implements IRBTVisitor { +public class TreeShower implements IRBTVisitor { private static final JoafipLogger LOGGER = JoafipLogger .getLogger(TreeShower.class); - private static final String TREE_END = "TREE END ----------------------------------------"; + private static final String TREE_END = "TREE END ----------------------------------------\n"; - private static final String TREE_BEGIN = "TREE BEGIN ----------------------------------------"; + private static final String TREE_BEGIN = "TREE BEGIN ----------------------------------------\n"; - private static final TreeShower INSTANCE = new TreeShower(); - private static final String TWO_SPACE = " "; private transient int pad; private final transient Stack<ObjectIdentityKey> visitStack = new Stack<ObjectIdentityKey>(); + private final StringBuilder stringBuilder = new StringBuilder(); + private boolean fatal; - public static TreeShower getInstance() { - return INSTANCE; - } - - private TreeShower() { + public TreeShower() { super(); } @SuppressWarnings("unchecked") public void showFatal(final IRBTVisitable visitable) throws RBTException { fatal = true; - log(TREE_BEGIN); + stringBuilder.append(TREE_BEGIN); pad = 0; visitStack.clear(); visitable.accept(this); visitStack.clear(); - log(TREE_END); + stringBuilder.append(TREE_END); + log(stringBuilder.toString()); } @SuppressWarnings("unchecked") public void show(final IRBTVisitable visitable) throws RBTException { fatal = false; - log(TREE_BEGIN); + stringBuilder.append(TREE_BEGIN); pad = 0; visitStack.clear(); visitable.accept(this); visitStack.clear(); - log(TREE_END); + stringBuilder.append(TREE_END); + log(stringBuilder.toString()); } public void beginVisit(final IRBTNode node) throws RBTException { final ObjectIdentityKey item = new ObjectIdentityKey(node); if (visitStack.contains(item)) { - log("--> " + node.toString()); + stringBuilder.append("--> "); + stringBuilder.append(node.toString()); + stringBuilder.append('\n'); throw new RBTException("cycle in tree"); } visitStack.push(item); pad++; - final StringBuilder stringBuilder = new StringBuilder(); for (int index = 0; index < pad; index++) { stringBuilder.append(TWO_SPACE); } stringBuilder.append(node.toString()); - log(stringBuilder.toString()); + stringBuilder.append('\n'); } public void endVisit(final IRBTNode node) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |