/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.util.Comparator;
/**
* Data structure that mantains data in a ordered binary tree; each node is
* greater (smaller) or equal than its 2 sub-nodes, for all the hierarchy.
*
* Elements of this data structure should either implement Comparable, or a
* Comparator should be given as argument to the constructor.
*
* @author Simone Bordet
* @version $Revision: 2787 $
*/
@SuppressWarnings("unchecked")
public class Heap {
private Comparator m_comparator;
private int m_count;
private Object[] m_nodes;
/**
* Creates a new Heap whose elements inserted implement the {@link Comparable}
* interface.
*/
public Heap() {
this(null);
}
/**
* Creates a new Heap whose elements are compared using the given
* {@link Comparator}.
*
* @param comparator
*/
public Heap(Comparator comparator) {
m_comparator = comparator;
clear();
}
/**
* Inserts the given element in this heap.
*
* @param obj
*
* @see #extract
*/
public void insert(Object obj) {
int length = m_nodes.length;
// Expand if necessary
if (m_count == length) {
Object[] newNodes = new Object[length + length];
System.arraycopy(m_nodes, 0, newNodes, 0, length);
m_nodes = newNodes;
}
// Be cur_slot the first unused slot index; be par_slot its parent index.
// Start from cur_slot and walk up the tree comparing the object to
// insert with the object at par_slot; if it's smaller move down the object
// at par_slot,
// otherwise cur_slot is the index where insert the object. If not done,
// shift up the tree so that now cur_slot is the old par_slot and
// par_slot is the parent index of the new cur_slot (so the grand-parent
// index of the old cur_slot) and compare again.
int k = m_count;
while (k > 0) {
int par = parent(k);
if (compare(obj, m_nodes[par]) < 0) {
m_nodes[k] = m_nodes[par];
k = par;
} else
break;
}
m_nodes[k] = obj;
++m_count;
}
/**
* Removes and returns the least element of this heap.
*
* @return the extracted object
*
* @see #insert
* @see #peek
*/
public Object extract() {
if (m_count < 1) {
return null;
} else {
int length = m_nodes.length >> 1;
// Shrink if necessary
if (length > 5 && m_count < (length >> 1)) {
Object[] newNodes = new Object[length];
System.arraycopy(m_nodes, 0, newNodes, 0, length);
m_nodes = newNodes;
}
//
int k = 0;
Object ret = m_nodes[k];
--m_count;
Object last = m_nodes[m_count];
for (;;) {
int l = left(k);
if (l >= m_count) {
break;
} else {
int r = right(k);
int child = (r >= m_count || compare(m_nodes[l], m_nodes[r]) < 0) ? l : r;
if (compare(last, m_nodes[child]) > 0) {
m_nodes[k] = m_nodes[child];
k = child;
} else {
break;
}
}
}
m_nodes[k] = last;
m_nodes[m_count] = null;
return ret;
}
}
/**
* @return without removing it, the least element of this heap.
*
* @see #extract
*/
public Object peek() {
if (m_count < 1) {
return null;
} else {
return m_nodes[0];
}
}
/**
* Empties this heap
*/
public void clear() {
m_count = 0;
m_nodes = new Object[10];
}
protected int compare(Object o1, Object o2) {
if (m_comparator != null) {
return m_comparator.compare(o1, o2);
} else {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -((Comparable) o2).compareTo(o1);
}
} else {
return ((Comparable) o1).compareTo(o2);
}
}
}
/**
* @return the parent index of index
.
* @param index
*/
protected int parent(int index) {
return (index - 1) >> 1;
}
/**
* @param index
* @return the left child index of index
.
*/
protected int left(int index) {
return index + index + 1;
}
/**
* @param index
* @return the right child index of index
.
*/
protected int right(int index) {
return index + index + 2;
}
}