Collections Data Structure Java

/*
 * 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;
  }
}