2 * Copyright (c) 2003, the JUNG Project and the Regents of the University
6 * This software is open-source under the BSD license; see either
8 * http://jung.sourceforge.net/license.txt for a description.
12 * Created on Oct 29, 2003
14 package edu.uci.ics.jung.algorithms.util;
16 import java.util.AbstractCollection;
17 import java.util.Collection;
18 import java.util.Comparator;
19 import java.util.HashMap;
20 import java.util.Iterator;
22 import java.util.NoSuchElementException;
23 import java.util.Queue;
24 import java.util.Vector;
26 import org.apache.commons.collections15.IteratorUtils;
29 * An array-based binary heap implementation of a priority queue,
31 * efficient <code>update()</code> and <code>contains</code> operations.
32 * It contains extra infrastructure (a hash table) to keep track of the
33 * position of each element in the array; thus, if the key value of an element
34 * changes, it may be "resubmitted" to the heap via <code>update</code>
35 * so that the heap can reposition it efficiently, as necessary.
37 * @author Joshua O'Madadhain
39 public class MapBinaryHeap<T>
40 extends AbstractCollection<T>
43 private Vector<T> heap = new Vector<T>(); // holds the heap as an implicit binary tree
44 private Map<T,Integer> object_indices = new HashMap<T,Integer>(); // maps each object in the heap to its index in the heap
45 private Comparator<T> comp;
46 private final static int TOP = 0; // the index of the top of the heap
49 * Creates a <code>MapBinaryHeap</code> whose heap ordering
50 * is based on the ordering of the elements specified by <code>c</code>.
52 public MapBinaryHeap(Comparator<T> comp)
58 * Creates a <code>MapBinaryHeap</code> whose heap ordering
59 * will be based on the <i>natural ordering</i> of the elements,
60 * which must be <code>Comparable</code>.
62 public MapBinaryHeap()
64 initialize(new ComparableComparator());
68 * Creates a <code>MapBinaryHeap</code> based on the specified
69 * collection whose heap ordering
70 * will be based on the <i>natural ordering</i> of the elements,
71 * which must be <code>Comparable</code>.
73 public MapBinaryHeap(Collection<T> c)
80 * Creates a <code>MapBinaryHeap</code> based on the specified collection
82 * is based on the ordering of the elements specified by <code>c</code>.
84 public MapBinaryHeap(Collection<T> c, Comparator<T> comp)
90 private void initialize(Comparator<T> comp)
97 * @see Collection#clear()
102 object_indices.clear();
107 * Inserts <code>o</code> into this collection.
110 public boolean add(T o)
112 int i = heap.size(); // index 1 past the end of the heap
119 * Returns <code>true</code> if this collection contains no elements, and
120 * <code>false</code> otherwise.
123 public boolean isEmpty()
125 return heap.isEmpty();
129 * Returns the element at the top of the heap; does not
135 return heap.elementAt(TOP);
141 * Removes the element at the top of this heap, and returns it.
142 * @deprecated Use {@link MapBinaryHeap#poll()}
143 * or {@link MapBinaryHeap#remove()} instead.
146 public T pop() throws NoSuchElementException
148 return this.remove();
152 * Returns the size of this heap.
161 * Informs the heap that this object's internal key value has been
162 * updated, and that its place in the heap may need to be shifted
166 public void update(T o)
168 // Since we don't know whether the key value increased or
169 // decreased, we just percolate up followed by percolating down;
170 // one of the two will have no effect.
172 int cur = object_indices.get(o).intValue(); // current index
173 int new_idx = percolateUp(cur, o);
174 percolateDown(new_idx);
178 * @see Collection#contains(java.lang.Object)
181 public boolean contains(Object o)
183 return object_indices.containsKey(o);
187 * Moves the element at position <code>cur</code> closer to
188 * the bottom of the heap, or returns if no further motion is
189 * necessary. Calls itself recursively if further motion is
192 private void percolateDown(int cur)
194 int left = lChild(cur);
195 int right = rChild(cur);
198 if ((left < heap.size()) &&
199 (comp.compare(heap.elementAt(left), heap.elementAt(cur)) < 0)) {
205 if ((right < heap.size()) &&
206 (comp.compare(heap.elementAt(right), heap.elementAt(smallest)) < 0)) {
213 percolateDown(smallest);
218 * Moves the element <code>o</code> at position <code>cur</code>
219 * as high as it can go in the heap. Returns the new position of the
220 * element in the heap.
222 private int percolateUp(int cur, T o)
226 while ((i > TOP) && (comp.compare(heap.elementAt(parent(i)), o) > 0))
228 T parentElt = heap.elementAt(parent(i));
229 heap.setElementAt(parentElt, i);
230 object_indices.put(parentElt, new Integer(i)); // reset index to i (new location)
234 // place object in heap at appropriate place
235 object_indices.put(o, new Integer(i));
236 heap.setElementAt(o, i);
242 * Returns the index of the left child of the element at
243 * index <code>i</code> of the heap.
245 * @return the index of the left child of the element at
246 * index <code>i</code> of the heap
248 private int lChild(int i)
254 * Returns the index of the right child of the element at
255 * index <code>i</code> of the heap.
257 * @return the index of the right child of the element at
258 * index <code>i</code> of the heap
260 private int rChild(int i)
266 * Returns the index of the parent of the element at
267 * index <code>i</code> of the heap.
269 * @return the index of the parent of the element at index i of the heap
271 private int parent(int i)
277 * Swaps the positions of the elements at indices <code>i</code>
278 * and <code>j</code> of the heap.
282 private void swap(int i, int j)
284 T iElt = heap.elementAt(i);
285 T jElt = heap.elementAt(j);
287 heap.setElementAt(jElt, i);
288 object_indices.put(jElt, new Integer(i));
290 heap.setElementAt(iElt, j);
291 object_indices.put(iElt, new Integer(j));
295 * Comparator used if none is specified in the constructor.
296 * @author Joshua O'Madadhain
298 private class ComparableComparator implements Comparator<T>
301 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
303 @SuppressWarnings("unchecked")
304 public int compare(T arg0, T arg1)
306 if (!(arg0 instanceof Comparable) || !(arg1 instanceof Comparable))
307 throw new IllegalArgumentException("Arguments must be Comparable");
309 return ((Comparable<T>)arg0).compareTo(arg1);
314 * Returns an <code>Iterator</code> that does not support modification
318 public Iterator<T> iterator()
320 return IteratorUtils.<T>unmodifiableIterator(heap.iterator());
324 * This data structure does not support the removal of arbitrary elements.
327 public boolean remove(Object o)
329 throw new UnsupportedOperationException();
333 * This data structure does not support the removal of arbitrary elements.
336 public boolean removeAll(Collection<?> c)
338 throw new UnsupportedOperationException();
342 * This data structure does not support the removal of arbitrary elements.
345 public boolean retainAll(Collection<?> c)
347 throw new UnsupportedOperationException();
350 public T element() throws NoSuchElementException
354 throw new NoSuchElementException();
358 public boolean offer(T o)
368 T bottom_elt = heap.lastElement();
369 heap.setElementAt(bottom_elt, TOP);
370 object_indices.put(bottom_elt, new Integer(TOP));
372 heap.setSize(heap.size() - 1); // remove the last element
376 object_indices.remove(top);
385 throw new NoSuchElementException();