// Merge two subtrees together, returning the one that came out on top. // For a pairing heap, merging consists of adding the larger node // to the sub list of the smaller. private HeapNode <T> merge(HeapNode <T> a, HeapNode <T> b) { if (compare(a.getNode(), b.getNode()) <= 0) // a <= b (swap a and b) { HeapNode <T> tmp = a; a = b; b = tmp; } // Here we assume that a > b, therefore a is added to b's children // Remove a from any child list it might be in. a.extract(); // Link a into b's child list b.addChild(a); return(b); }
// Delete the mininum node, and return it. This is where the log n // magic happens. Pairs the sub-list together, then sweeps up the pairs // into one tree again. public T deleteMin() { if (isEmpty()) { return(default(T)); } // NOTE: the final_cast is needed so the user can modify his own data. T ret = top.getNode(); HeapNode <T> newtop, i, j; if (top.getChild() == null) // Only one element in heap { top = null; size--; return(ret); } // First of two passes: combine pairs of roots together, from // left to right. i = top.getChild(); // Note, end condition is too complicated for more generalized loops while (true) { // i is the first, j is the second if ((j = i.getNext()) == null) // If i is the odd man out (no partner j) { break; } if (i == merge(i, j)) // i came out on top { if (i.getNext() == null) // i is now the last in the loop { break; } i = i.getNext(); } else // j came out on top { if (j.getNext() == null) // j is the last in the loop { i = j; // As a set up for the next pass break; } i = j.getNext(); } } // Iterate the other way, combining each new tree with the rightmost newtop = i; j = i.getPrev(); while (j != null) { newtop = merge(newtop, j); j = newtop.getPrev(); } top = newtop; size--; return(ret); }
public T pop() { if (root == null) { return(default(T)); } Queue <HeapNode <T> > q = new Queue <HeapNode <T> >(); HeapNode <T> curr = root; HeapNode <T> prev = null; while (curr != null) { HeapNode <T> l = curr.getLeft(); q.Enqueue(l); HeapNode <T> r = curr.getRight(); q.Enqueue(r); prev = curr; curr = q.Dequeue(); } //case where root is the only one //handle it here to avoid null pointers below if (prev.Equals(root)) { root = null; return(prev.getNode()); } //set last element in tree to root node //set roots left and right to new root left and right prev.setLeft(root.getLeft()); prev.setRight(root.getRight()); //set new root parents to this if (prev.getLeft() != null) { prev.getLeft().setParent(prev); } if (prev.getRight() != null) { prev.getRight().setParent(prev); } //set prev's old parent's left or right branch to null if (prev.getParent().getLeft().Equals(prev)) { prev.getParent().setLeft(null); } else if (prev.getParent().getRight().Equals(prev)) { prev.getParent().setRight(null); } //set prev parent to null since it will be the root prev.setParent(null); HeapNode <T> popVal = root; root = prev; //place prev in its correct place //root.sort(); root = root.sortChild(); //completely disconnect popped value from tree popVal.setParent(null); popVal.setLeft(null); popVal.setRight(null); return(popVal.getNode()); }