package net.datastructures; import java.util.Comparator; //begin#fragment HeapPriorityQueue /** * Realization of a priority queue by means of a heap. A complete * binary tree realized by means of an array list is used to * represent the heap. //end#fragment HeapPriorityQueue * * @author Roberto Tamassia, Michael Goodrich, Eric Zamore //begin#fragment HeapPriorityQueue */ public class HeapPriorityQueue implements PriorityQueue { protected CompleteBinaryTree> heap; // underlying heap protected Comparator comp; // comparator for the keys /** Inner class for heap entries. */ protected static class MyEntry implements Entry { protected K key; protected V value; public MyEntry(K k, V v) { key = k; value = v; } public K getKey() { return key; } public V getValue() { return value; } public String toString() { return "(" + key + "," + value + ")"; } } /** Creates an empty heap with the default comparator */ public HeapPriorityQueue() { heap = new ArrayListCompleteBinaryTree>(); // use an array list comp = new DefaultComparator(); // use the default comparator } /** Creates an empty heap with the given comparator */ public HeapPriorityQueue(Comparator c) { heap = new ArrayListCompleteBinaryTree>(); comp = c; } //end#fragment HeapPriorityQueue /** Sets the comparator used for comparing items in the heap. * @throws IllegalStateException if priority queue is not empty */ public void setComparator(Comparator c) throws IllegalStateException { if(!isEmpty()) // this is only allowed if the priority queue is empty throw new IllegalStateException("Priority queue is not empty"); comp = c; } //begin#fragment HeapPriorityQueue /** Returns the size of the heap */ public int size() { return heap.size(); } /** Returns whether the heap is empty */ public boolean isEmpty() { return heap.size() == 0; } //end#fragment HeapPriorityQueue //begin#fragment mainMethods /** Returns but does not remove an entry with minimum key */ public Entry min() throws EmptyPriorityQueueException { if (isEmpty()) throw new EmptyPriorityQueueException("Priority queue is empty"); return heap.root().element(); } /** Inserts a key-value pair and returns the entry created */ public Entry insert(K k, V x) throws InvalidKeyException { checkKey(k); // may throw an InvalidKeyException Entry entry = new MyEntry(k,x); upHeap(heap.add(entry)); return entry; } /** Removes and returns an entry with minimum key */ public Entry removeMin() throws EmptyPriorityQueueException { if (isEmpty()) throw new EmptyPriorityQueueException("Priority queue is empty"); Entry min = heap.root().element(); if (size() == 1) heap.remove(); else { heap.replace(heap.root(), heap.remove()); downHeap(heap.root()); } return min; } /** Determines whether a given key is valid */ protected void checkKey(K key) throws InvalidKeyException { try { comp.compare(key,key); } catch(Exception e) { throw new InvalidKeyException("Invalid key"); } } //end#fragment mainMethods //begin#fragment auxiliary /** Performs up-heap bubbling */ protected void upHeap(Position> v) { Position> u; while (!heap.isRoot(v)) { u = heap.parent(v); if (comp.compare(u.element().getKey(), v.element().getKey()) <= 0) break; swap(u, v); v = u; } } /** Performs down-heap bubbling */ protected void downHeap(Position> r) { while (heap.isInternal(r)) { Position> s; // the position of the smaller child if (!heap.hasRight(r)) s = heap.left(r); else if (comp.compare(heap.left(r).element().getKey(), heap.right(r).element().getKey()) <=0) s = heap.left(r); else s = heap.right(r); if (comp.compare(s.element().getKey(), r.element().getKey()) < 0) { swap(r, s); r = s; } else break; } } /** Swaps the entries of the two given positions */ protected void swap(Position> x, Position> y) { Entry temp = x.element(); heap.replace(x, y.element()); heap.replace(y, temp); } /** Text visualization for debugging purposes */ public String toString() { return heap.toString(); } //end#fragment auxiliary }