void redirectThreadsPointingToMe(FHthreadedNode<E> nodeToRemove) { FHthreadedNode<E> minNode, maxNode, node; // adjust nodes in root's subtree that "thread directly up" to root minNode = findMin(nodeToRemove); maxNode = findMax(nodeToRemove); for (node = minNode; node != null; node = successor(node)) if (node.lftThread && node.lftChild == nodeToRemove) { node.lftChild = predecessor(nodeToRemove); break; // last of only two possible threads pointing up } else if (node.rtThread && node.rtChild == nodeToRemove) { node.rtChild = successor(nodeToRemove); } }
// called when both flags are true, meaning one MUST be parent. find out // which one, so we can set parent's left of right thread flag to true protected FHthreadedNode<E> adjustParentThreadFlagsAndUnlink(FHthreadedNode<E> nodeToRemove) { FHthreadedNode<E> node; node = nodeToRemove.rtChild; // successor is parent? if (node != null) { if (node.lftChild == nodeToRemove) { node.lftThread = true; return nodeToRemove.lftChild; } } // test both in case mRoot is leaf node = nodeToRemove.lftChild; // predecessor is parent? if (node != null) { if (node.rtChild == nodeToRemove) { node.rtThread = true; return nodeToRemove.rtChild; } } return null; // shouldn't happen }
public boolean insert(E x) { int compareResult; if (mRoot == null) { mRoot = new FHthreadedNode<E>(x, null, null, true, true, 0); mSize++; return true; } FHthreadedNode<E> newNode, parent; parent = mRoot; while (true) { compareResult = x.compareTo(parent.data); if (compareResult < 0) { if (!(parent.lftThread)) parent = parent.lftChild; else { // place as new left child newNode = new FHthreadedNode<E>(x, parent.lftChild, parent, true, true, 0); parent.lftChild = newNode; parent.lftThread = false; break; } } else if (compareResult > 0) { if (!(parent.rtThread)) parent = parent.rtChild; else { // place as new right child newNode = new FHthreadedNode<E>(x, parent, parent.rtChild, true, true, 0); parent.rtChild = newNode; parent.rtThread = false; break; } } else return false; // duplicate } mSize++; return true; }
// very hard to remove recursion, so only adjust pred/succ links protected FHthreadedNode<E> remove(FHthreadedNode<E> root, E x) { int compareResult; // avoid multiple calls to compareTo() FHthreadedNode<E> tempRoot; if (root == null) return null; compareResult = x.compareTo(root.data); if (compareResult < 0) { if (!root.lftThread) root.lftChild = remove(root.lftChild, x); } else if (compareResult > 0) { if (!root.rtThread) root.rtChild = remove(root.rtChild, x); } // found the node else if (!(root.lftThread) && !(root.rtThread)) { // two real children root.data = findMin(root.rtChild).data; root.rtChild = remove(root.rtChild, root.data); } else { // one or two "fake" children => at least one thread redirectThreadsPointingToMe(root); // if a full leaf, we have to modify one of parent's thread flags if (root.lftThread && root.rtThread) { tempRoot = adjustParentThreadFlagsAndUnlink(root); // in case this was final node in tree if (root.lftChild == null && root.rtChild == null) mRoot = null; root = tempRoot; } else // at least one real child, so we copy to parent root = (!(root.lftThread)) ? root.lftChild : root.rtChild; mSize--; } return root; }