/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.common.pqueue; import java.util.Arrays; public class IntBinHeap implements OTPPriorityQueue<Integer> { private static final double GROW_FACTOR = 2.0; private double[] prio; private int[] elem; private int size; private int capacity; public IntBinHeap() { this(1000); } public IntBinHeap(int capacity) { if (capacity < 10) capacity = 10; this.capacity = capacity; size = 0; elem = new int[capacity + 1]; prio = new double[capacity + 1]; // 1-based indexing prio[0] = Double.NEGATIVE_INFINITY; // set sentinel } public int size() { return size; } public boolean empty() { return size <= 0; } public double peek_min_key() { if (size > 0) return prio[1]; else throw new IllegalStateException("An empty queue does not have a minimum key."); } public int p_peek_min() { if (size > 0) return elem[1]; else throw new IllegalStateException("An empty queue does not have a minimum value."); } public Integer peek_min() { if (size > 0) return p_peek_min(); else return null; } public void rekey(int e, double p) { // Perform "inefficient" but straightforward linear search // for an element then change its key by sifting up or down int i; for (i=1; i <= size; i++) { if (elem[i] == e) break; } if (i > size) { //System.out.printf("did not find element %s\n", e); return; } //System.out.printf("found element %s with key %f at %d\n", e, prio[i], i); if (p > prio[i]) { // sift up (as in extract) while (i*2 <= size) { int child = i * 2; if (child != size && prio[child+1] < prio[child]) child ++; if (p > prio[child]) { elem[i] = elem[child]; prio[i] = prio[child]; i = child; } else break; } elem[i] = e; prio[i] = p; } else { // sift down (as in insert) while (prio[i/2] > p) { elem[i] = elem[i/2]; prio[i] = prio[i/2]; i /= 2; } elem[i] = e; prio[i] = p; } } public void dump() { for (int i=0; i<=capacity; i++) { String topMarker = (i > size) ? "(UNUSED)" : ""; System.out.printf("%d\t%f\t%s\t%s\n", i, prio[i], elem[i], topMarker); } System.out.printf("-----------------------\n"); } public void reset() { // empties the queue in one operation size=0; } public void insert(int e, double p) { int i; size += 1; if (size > capacity) resize((int) (capacity * GROW_FACTOR)); for (i = size; prio[i/2] > p; i /= 2) { elem[i] = elem[i/2]; prio[i] = prio[i/2]; } elem[i] = e; prio[i] = p; } @Override public void insert(Integer payload, double key) { insert(payload.intValue(), key); } public int p_extract_min() { int i, child; int minElem = elem[1]; int lastElem = elem[size]; double lastPrio = prio[size]; if (size <= 0) throw new IllegalStateException("An empty queue does not have a minimum value."); size -= 1; for (i=1; i*2 <= size; i=child) { child = i*2; if (child != size && prio[child+1] < prio[child]) child++; if (lastPrio > prio[child]) { elem[i] = elem[child]; prio[i] = prio[child]; } else break; } elem[i] = lastElem; prio[i] = lastPrio; return minElem; } @Override public Integer extract_min() { if (size <= 0) return null; else return p_extract_min(); } public void resize(int capacity) { // System.out.println("Growing queue to " + capacity); if (capacity < size) throw new IllegalStateException("BinHeap contains too many elements to fit in new capacity."); this.capacity = capacity; prio = Arrays.copyOf(prio, capacity + 1); elem = Arrays.copyOf(elem, capacity + 1); } @Override public void insert_or_dec_key(Integer payload, double key) { throw new UnsupportedOperationException(); } }