public class MaxHeap implements SeqStructure { private BinaryNode root; private BinaryNode finger; //a cursor into the data structure private BinaryNode previous; //previous is one step behind finger private int size; private int nComparisons; public MaxHeap() { root= null; size = 0; nComparisons = 0; } public String toString() { return root.toString(); } public String toTree() { return root.toTree(); } public int numComparisons() { return nComparisons; } public boolean isEmpty() { return size == 0; } public int size() { return this.size; } public Object get() { // check for empty heap if (isEmpty()) { System.out.println("Empty heap!"); return null; } // extract the maximum element Comparable max = (Comparable)(root.getItem()); // if empty tree remains after deletion, update is easy if (size == 1) { root = null; size = 0; return max; } // non-empty tree will remain after deletion of root // move down the tree to PARENT of node whose number is size // easy to show that number of this parent node is size/2 heapDecoder d = new heapDecoder(size/2, 2); finger = root; while (d.hasMoreDigits()) if (d.getNextDigit() == 0) finger = finger.getLeft(); else finger = finger.getRight(); // set root value to value in node whose number is size // delete node whose number is size if (size%2 == 0) { // left child root.setItem(finger.getLeft().getItem()); finger.setLeft(null); } else { root.setItem(finger.getRight().getItem()); finger.setRight(null); } // now walk down the tree from the root restoring the heap property BinaryNode dNode = root; // the disturbed node BinaryNode cNode; // max child of dNode while (true) { // check the left and right children for heap property BinaryNode l = dNode.getLeft(); BinaryNode r = dNode.getRight(); // find the max kid if (l == null) break; //d must be a leaf node if (r == null) cNode = l; else { // dNode has two children if (((Comparable)l.getItem()).compareTo(r.getItem()) < 0) cNode = r; else cNode = l; nComparisons++; } // swap maxkid with parent maybe? nComparisons++; if (((Comparable)dNode.getItem()).compareTo(cNode.getItem()) < 0) { // swap parent and child data fields and update dNode Object o = dNode.getItem(); dNode.setItem(cNode.getItem()); cNode.setItem(o); dNode = cNode; } else // no need to go further down heap break; } size = size - 1; return max; } public void put(Object o) { Comparable p = (Comparable)o; size = size + 1; if (root == null) { root = new BinaryNode(p); return; } // otherwise move down the tree to parent of node whose number is size // along the way, compare values to maintain heap property heapDecoder d = new heapDecoder(size/2,2); finger = root; while (true) { if (p.compareTo(finger.getItem()) > 0) { //swap Comparable temp = (Comparable) finger.getItem(); finger.setItem(p); p = temp; } nComparisons++; if (! d.hasMoreDigits()) { BinaryNode n = new BinaryNode(p); if (size%2 == 0) //set left finger.setLeft(n); else finger.setRight(n); break; } else { if (d.getNextDigit() == 0) //go left finger = finger.getLeft(); else //go right finger = finger.getRight(); } } } // inner class that implements an iterator for translating heap position numbers // into paths down the tree from root to that position // base will usually be 2 (binary heaps) but it can be set arbitrarily // for more general n-ary heaps private class heapDecoder { private int position; private int base; public heapDecoder(int pos, int base){ position = pos; this.base = base; } public int getNextDigit() { int rem = position % base; position = position/base; return rem; } public boolean hasMoreDigits() { return (position > 1); } } }