/** * Cuts a node from its parent. If the parent was already marked, recursively cuts that node from * its parent as well. * * @param entry The node to cut from its parent. */ private void cutNode(Entry<T> entry) { /* Begin by clearing the node's mark, since we just cut it. */ entry.mIsMarked = false; /* Base case: If the node has no parent, we're done. */ if (entry.mParent == null) return; /* Rewire the node's siblings around it, if it has any siblings. */ if (entry.mNext != entry) { // Has siblings entry.mNext.mPrev = entry.mPrev; entry.mPrev.mNext = entry.mNext; } /* If the node is the one identified by its parent as its child, * we need to rewrite that pointer to point to some arbitrary other * child. */ if (entry.mParent.mChild == entry) { /* If there are any other children, pick one of them arbitrarily. */ if (entry.mNext != entry) { entry.mParent.mChild = entry.mNext; } /* Otherwise, there aren't any children left and we should clear the * pointer and drop the node's degree. */ else { entry.mParent.mChild = null; } } /* Decrease the degree of the parent, since it just lost a child. */ --entry.mParent.mDegree; /* Splice this tree into the root list by converting it to a singleton * and invoking the merge subroutine. */ entry.mPrev = entry.mNext = entry; mMin = mergeLists(mMin, entry); /* Mark the parent and recursively cut it if it's already been * marked. */ if (entry.mParent.mIsMarked) cutNode(entry.mParent); else entry.mParent.mIsMarked = true; /* Clear the relocated node's parent; it's now a root. */ entry.mParent = null; }
/** * Dequeues and returns the minimum element of the Fibonacci heap. If the heap is empty, this * throws a NoSuchElementException. * * @return The smallest element of the Fibonacci heap. * @throws NoSuchElementException If the heap is empty. */ public Entry<T> dequeueMin() { /* Check for whether we're empty. */ if (isEmpty()) throw new NoSuchElementException("Heap is empty."); /* Otherwise, we're about to lose an element, so decrement the number of * entries in this heap. */ --mSize; /* Grab the minimum element so we know what to return. */ Entry<T> minElem = mMin; /* Now, we need to get rid of this element from the list of roots. There * are two cases to consider. First, if this is the only element in the * list of roots, we set the list of roots to be null by clearing mMin. * Otherwise, if it's not null, then we write the elements next to the * min element around the min element to remove it, then arbitrarily * reassign the min. */ if (mMin.mNext == mMin) { // Case one mMin = null; } else { // Case two mMin.mPrev.mNext = mMin.mNext; mMin.mNext.mPrev = mMin.mPrev; mMin = mMin.mNext; // Arbitrary element of the root list. } /* Next, clear the parent fields of all of the min element's children, * since they're about to become roots. Because the elements are * stored in a circular list, the traversal is a bit complex. */ if (minElem.mChild != null) { /* Keep track of the first visited node. */ Entry<?> curr = minElem.mChild; do { curr.mParent = null; /* Walk to the next node, then stop if this is the node we * started at. */ curr = curr.mNext; } while (curr != minElem.mChild); } /* Next, splice the children of the root node into the topmost list, * then set mMin to point somewhere in that list. */ mMin = mergeLists(mMin, minElem.mChild); /* If there are no entries left, we're done. */ if (mMin == null) return minElem; /* Next, we need to coalsce all of the roots so that there is only one * tree of each degree. To track trees of each size, we allocate an * ArrayList where the entry at position i is either null or the * unique tree of degree i. */ List<Entry<T>> treeTable = new ArrayList<Entry<T>>(); /* We need to traverse the entire list, but since we're going to be * messing around with it we have to be careful not to break our * traversal order mid-stream. One major challenge is how to detect * whether we're visiting the same node twice. To do this, we'll * spent a bit of overhead adding all of the nodes to a list, and * then will visit each element of this list in order. */ List<Entry<T>> toVisit = new ArrayList<Entry<T>>(); /* To add everything, we'll iterate across the elements until we * find the first element twice. We check this by looping while the * list is empty or while the current element isn't the first element * of that list. */ for (Entry<T> curr = mMin; toVisit.isEmpty() || toVisit.get(0) != curr; curr = curr.mNext) toVisit.add(curr); /* Traverse this list and perform the appropriate unioning steps. */ for (Entry<T> curr : toVisit) { /* Keep merging until a match arises. */ while (true) { /* Ensure that the list is long enough to hold an element of this * degree. */ while (curr.mDegree >= treeTable.size()) treeTable.add(null); /* If nothing's here, we're can record that this tree has this size * and are done processing. */ if (treeTable.get(curr.mDegree) == null) { treeTable.set(curr.mDegree, curr); break; } /* Otherwise, merge with what's there. */ Entry<T> other = treeTable.get(curr.mDegree); treeTable.set(curr.mDegree, null); // Clear the slot /* Determine which of the two trees has the smaller root, storing * the two tree accordingly. */ Entry<T> min = (other.mPriority < curr.mPriority) ? other : curr; Entry<T> max = (other.mPriority < curr.mPriority) ? curr : other; /* Break max out of the root list, then merge it into min's child * list. */ max.mNext.mPrev = max.mPrev; max.mPrev.mNext = max.mNext; /* Make it a singleton so that we can merge it. */ max.mNext = max.mPrev = max; min.mChild = mergeLists(min.mChild, max); /* Reparent max appropriately. */ max.mParent = min; /* Clear max's mark, since it can now lose another child. */ max.mIsMarked = false; /* Increase min's degree; it now has another child. */ ++min.mDegree; /* Continue merging this tree. */ curr = min; } /* Update the global min based on this node. Note that we compare * for <= instead of < here. That's because if we just did a * reparent operation that merged two different trees of equal * priority, we need to make sure that the min pointer points to * the root-level one. */ if (curr.mPriority <= mMin.mPriority) mMin = curr; } return minElem; }