/******************************************************************************* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library 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 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package alma.ACS.jbaci; import java.util.Comparator; /** * A heap-based priority queue. * The class currently uses a standard array-based heap, as described * in, for example, Sedgewick's Algorithms text. All methods are fully synchronized. **/ public class Heap { /** * The tree nodes, packed into an array. */ protected Object[] nodes_; /** * Number of used slots. */ protected int count_ = 0; // number of used slots /** * Ordering comparator. */ protected final Comparator cmp_; /** * Create a Heap with the given initial capacity and comparator * @param capacity initial capacity. * @param cmp comparator instance. * @exception IllegalArgumentException if capacity less or equal to zero **/ public Heap(int capacity, Comparator cmp) throws IllegalArgumentException { if (capacity <= 0) throw new IllegalArgumentException(); nodes_ = new Object[capacity]; cmp_ = cmp; } /** * Create a Heap with the given capacity, and relying on natural ordering. * @param capacity initial capacity. **/ public Heap(int capacity) { this(capacity, null); } /** * Perform element comparisons using comparator or natural ordering. **/ protected int compare(Object a, Object b) { if (cmp_ == null) return ((Comparable) a).compareTo(b); else return cmp_.compare(a, b); } /** * Get parent index. */ protected final int parent(int k) { return (k - 1) / 2; } /** * Get left child. */ protected final int left(int k) { return 2 * k + 1; } /** * Get right child. */ protected final int right(int k) { return 2 * (k + 1); } /** * Insert an element, resize if necessary. * @param x object to insert. **/ public synchronized void insert(Object x) { if (count_ >= nodes_.length) { int newcap = 3 * nodes_.length / 2 + 1; Object[] newnodes = new Object[newcap]; System.arraycopy(nodes_, 0, newnodes, 0, nodes_.length); nodes_ = newnodes; } int k = count_; ++count_; while (k > 0) { int par = parent(k); if (compare(x, nodes_[par]) < 0) { nodes_[k] = nodes_[par]; k = par; } else break; } nodes_[k] = x; } /** * Return and remove least element, or null if empty. * @return extraced least element. **/ public synchronized Object extract() { if (count_ < 1) return null; int k = 0; // take element at root; Object least = nodes_[k]; --count_; Object x = nodes_[count_]; nodes_[count_] = null; for (;;) { int l = left(k); if (l >= count_) break; else { int r = right(k); int child = (r >= count_ || compare(nodes_[l], nodes_[r]) < 0) ? l : r; if (compare(x, nodes_[child]) > 0) { nodes_[k] = nodes_[child]; k = child; } else break; } } nodes_[k] = x; return least; } /** * Return least element without removing it, or null if empty. * @return least element. **/ public synchronized Object peek() { if (count_ > 0) return nodes_[0]; else return null; } /** * Return number of elements. * @return number of elements. **/ public synchronized int size() { return count_; } /** * Remove all elements. **/ public synchronized void clear() { for (int i = 0; i < count_; ++i) nodes_[i] = null; count_ = 0; } }