Monday, December 2, 2013

Heap: Version 1

//generic heap class based on arraylist
import java.util.ArrayList;

//extending the Comparable makes the compareTo method available
public class Heap {
  //initialize a generic arraylist instance 
  private ArrayList list = new ArrayList();

  /** Create a default heap */
  public Heap() {
  }

  /** Create a heap from an array of objects */
  public Heap(E[] objects) {
    for (int i = 0; i < objects.length; i++)
      //this add method should be called something more like heapify
      //but the class ArrayList has an add method that should be reimplemented
      //for heaps...this is following a design pattern
      add(objects[i]);
  }

  /** Add a new object into the heap */
  public void add(E newObject) {
    list.add(newObject); // Append to the heap
    int currentIndex = list.size() - 1; // The index of the last node
    //this while loop heapifies the new array.
    while (currentIndex > 0) {
      int parentIndex = (currentIndex - 1) / 2;
      // Swap if the current object is greater than its parent
      if (list.get(currentIndex).compareTo(
          list.get(parentIndex)) > 0) {
        E temp = list.get(currentIndex);
        list.set(currentIndex, list.get(parentIndex));
        list.set(parentIndex, temp);
      }
      else
        break; // the tree is a heap now

      currentIndex = parentIndex;
    }
  }

  /** Remove the root from the heap */
  public E remove() {
    if (list.size() == 0) return null;
    //return root of heap 
    E removedObject = list.get(0);
    list.set(0, list.get(list.size() - 1));
    //make list 1 element smaller
    list.remove(list.size() - 1);
    
    //while loop to heapify the new array
    int currentIndex = 0;
    while (currentIndex < list.size()) {
      int leftChildIndex = 2 * currentIndex + 1;
      int rightChildIndex = 2 * currentIndex + 2;

      // Find the maximum between two children
      if (leftChildIndex >= list.size()) break; // The tree is a heap
      int maxIndex = leftChildIndex;
      if (rightChildIndex < list.size()) {
        if (list.get(maxIndex).compareTo(
            list.get(rightChildIndex)) < 0) {
          maxIndex = rightChildIndex;
        }
      }

      // Swap if the current node is less than the maximum
      if (list.get(currentIndex).compareTo(
          list.get(maxIndex)) < 0) {
        E temp = list.get(maxIndex);
        list.set(maxIndex, list.get(currentIndex));
        list.set(currentIndex, temp);
        currentIndex = maxIndex;
      }
      else
        break; // The tree is a heap
    }

    return removedObject;
  }

  /** Get the number of nodes in the tree */
  public int getSize() {
    return list.size();
  }
}
EDIT: line 4 is not rendering correctly. sorry. :(
Comments: Because heaps a binary tree most of the basic dynamic set operations can be implemented on a heap in O(log n), or in time that is at worst the height of the heap. In fact, the reason why the above code works is due to the fact that we are interacting with an array as a heap. Application #1: Sorting
 
/** Heap sort method */
  public static  void heapSort(E[] list) {
    // Create a Heap of integers
    Heap heap = new Heap();

    // Add elements to the heap
    for (int i = 0; i < list.length; i++)
      heap.add(list[i]);

    // Remove elements from the heap
    for (int i = list.length - 1; i >= 0; i--)
      list[i] = heap.remove();
  }
  
  /** A test method */
  public static void main(String[] args) {
    Integer[] list = {2, 3, 2, 5, 6, 1, -2, 3, 14, 12};
    heapSort(list);
    for (int i = 0; i < list.length; i++)
      System.out.print(list[i] + " ");
  }
}
EDIT: line 2 of Heapsort is not rendering correctly. Sorry.

 Comments: Sorting with a heap is probably the easiest application of the heap. In the near future I will apply heaps to different problems. Also, I will implement variations of heaps like the binomial heap, Fibonacci heap, and soft heap.

No comments:

Post a Comment