Assignment 10 - COP 3530, Fall 2007

Please read the assignment submission rules and the academic dishonesty page before you start work on this assignment. Failure to comply by these rules will cost a significant percentage of your assignment grade.

Make sure your classes are in the package dataStructures. If you do not understand what packages are you can read this tutorial. If you have trouble with the classpath settings you could try reading this tutorial.
Unless stated otherwise, you are not allowed to use any classes from the dataStructures or the java.util packages.

 



In this assignment you will modify the heap data structure and algorithms to get an implementation of a min-max heap, which can be used to find the minimum and the maximum in constant time, while still supporting O(log n) insertion and deletion and linear time initialization.

In a min-max heap one arranges the records so that each node at even depth has key value greater than that of any of its descendants, and each node at odd depth has key value less than that of any of its descendants. Note that like min heaps and max heaps, min-max heaps are always complete trees.

sample min-max heap

Here the circles are on odd levels, so they will always be smaller than their descendants. Hence the smallest element in the tree is 2. The nodes shown as a square are on even levels, so their key values will always be larger than their descendants. For example here 25 is larger than 17,5,21,18 and 6.
  1. Implement the methods getMax() and getMin(). These methods return the maximum (or minimum for getMin) element, but they don't modify the heap in any way. You can use the given initialize() methods to create a heap and test your implementations. These methods need to run in constant time.
  2. Implement the method put(Comparable), which adds an element into the min-max heap. This methods needs to run in logarithmic time. Note that if the capacity gets full, you will have to increase the capacity of the "heap"( i.e. create a new array then copy all elements into it). The time consumption caused by these capacity modifications should not be taken into account for the running time requirement.
  3. Implement the methods removeMin() and removeMax(). These methods remove the maximum (or minimum) elements from the heap and return them. The running times for these methods need to be logarithmic.

Notes:
  1. The initialize() method is given as both a demonstration and starting point. We suggest you study the method to get a better understanding of the date structure.
  2. You are not allowed to use any other data structures.
  3. You are allowed to use the given helper methods.
  4. If your implementation does not satisfy the running time requirements, you will lose most of the points for that problem.

package dataStructures;

public class MinMaxHeap implements MaxPriorityQueue, MinPriorityQueue {

    // data members
    Comparable[] heap;   // array for complete binary tree
    int size;             // number of elements in heap
   //add any helper method when necessary

    public MinMaxHeap(int initialCapacity) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException
                ("initialCapacity must be >= 1");
        heap = new Comparable[initialCapacity + 1];
        size = 0;
    }

    public MinMaxHeap() {
        this(10);
    }


    public boolean isEmpty() {
        return size == 0;
    }

    public int size() {
        return size;
    }

    public Comparable getMax() {
        //your code here
    }

    public Comparable getMin() {
        // your code here
    }

    public void put(Comparable theObject) {
        // your code here

    }

    public Comparable removeMax() {
        // your code here
    }


    public Comparable removeMin() {
        //your code here

    }

    public void initialize(Comparable[] theHeap, int theSize) {

        heap = theHeap;
        size = theSize;

        for (int root = size / 2; root >= 1; root--) {
            if (isMinLevel(root)) {
                processMinLevel(root);
            else //max level
                processMaxLevel(root);
            }
        }
    }


    //method used by initialize()
    private void processMinLevel(int root) {

        int child;
        while ((child = root * 2<= size) {//root has at least one child
            int minchild = -1;
            int mingrandchild = -1;
            int grandchild = * child;
            minchild = child;
            //find smallest grandchild if there is one
            if (grandchild <= sizemingrandchild = grandchild++;
            while (grandchild <= size && grandchild <= child * 3) {
                if (heap[grandchild].compareTo(heap[mingrandchild]) 0)
                    mingrandchild = grandchild;
                grandchild++;
            }
            //find smallest child
            if (child < size &&
                heap[child].compareTo(heap[child + 1]) 0minchild++;
            //check if minchild is smaller than the grandchildren
            if (mingrandchild == -||
                heap[minchild].compareTo(heap[mingrandchild]) 0) {
                if (heap[minchild].compareTo(heap[root]) 0)
                    swap(minchild, root);
                break;
            }
            if (heap[mingrandchild].compareTo(heap[root]) 0) {
                swap(root, mingrandchild);
                //now the grandchilds parent might be smaller than the grandchild
                int parent = mingrandchild / 2;
                if (heap[parent].compareTo(heap[mingrandchild]) 0) {
                    swap(parent, mingrandchild);
                }
                root = mingrandchild; //need to continue with the grandchild
            else break;
        }
    }

    //method used by initialize()
    private void processMaxLevel(int root) {

        int child;

        while ((child = root * 2<= size) {
            int maxchild = -1;
            int maxgrandchild = -1;
            int grandchild = * child;
            maxchild = child;
            if (grandchild <= sizemaxgrandchild = grandchild++;
            while (grandchild <= size && grandchild <= child * 3) {
                if (heap[grandchild].compareTo(heap[maxgrandchild]) 0)
                    maxgrandchild = grandchild;
                grandchild++;
            }
            if (child < size &&
                heap[child].compareTo(heap[child + 1]) 0maxchild++;
            if (maxgrandchild == -||
                heap[maxchild].compareTo(heap[maxgrandchild]) 0) {
                if (heap[maxchild].compareTo(heap[root]) 0)
                    swap(maxchild, root);
                break;
            }
            if (heap[maxgrandchild].compareTo(heap[root]) 0) {
                swap(root, maxgrandchild);
                int parent = maxgrandchild / 2;
                if (heap[parent].compareTo(heap[maxgrandchild]) 0) {
                    swap(parent, maxgrandchild);
                }
                root = maxgrandchild;
            else break;
        }
    }

    //swaps the elements with the given indices in the heap
    private void swap(int m, int n) {

        Comparable temp = heap[n];
        heap[n= heap[m];
        heap[m= temp;

    }

    //returns true if the node is in the min level, false otherwise
    private boolean isMinLevel(int node) {
        return (int) (Math.log(node/ Math.log(2)) == 0;
    }

    public String toString() {
        StringBuffer s = new StringBuffer();
        s.append("The " + size + " elements are [");
        if (size > 0) {// nonempty heap
            // do first element
            s.append(heap[1]);
            // do remaining elements
            for (int i = 2; i <= size; i++)
                s.append(", " + heap[i]);
        }
        s.append("]");

        return new String(s);
    }


    public int lb(int n) {
        int v = 0;
        while (n > 0) {
            n = n / 2;
            v++;
        }
        return v;
    }

    public void print() {        //print the heap as a tree
        int depth = lb(size);
        int space = ^ depth;
        for (int i = 0; i < depth; i++) {
            space = (<< (depth - i)) 2;
            String blank = "";
            String out = "";
            for (int j = 0; j < space; j++) {
                out += "\t";
            }
            for (int j = 0; j < space; j++) {
                blank += "\t\t";
            }

            for (int j = 0; j < << (i); j++) {
                int index = j + (<< (i)) 1;
                if (index >= size) {
                    break;
                }
                if (heap[index + 1!= null) {
                    out += heap[index + 1].toString() + blank;
                else {
                    out += "n" + blank;
                }
            }
            System.out.println(out);
        }

    }

    public static void main(String[] args) {

        MinMaxHeap h = new MinMaxHeap(1);

        h.put(new Integer(-72));
        h.put(new Integer(56));
        h.put(new Integer(39));
        h.put(new Integer(-29));
        h.put(new Integer(93));
        h.put(new Integer(7));
        h.put(new Integer(-19));
        h.put(new Integer(26));
        h.put(new Integer(2));
        h.put(new Integer(-1));

        //h.print();

        System.out.println("Elements in array order are");
        System.out.println(h);
        System.out.println();

        // test remove max
        System.out.println("The min element is " + h.getMin());
        System.out.println("The max element is " + h.getMax());


        for (int i = 0; i < 2; i++) {
            System.out.println("Deleted min element " + h.removeMin());
            //h.print();
            System.out.println();
        }
        System.out.println(h);
        for (int i = 0; i < 2; i++) {
            System.out.println("Deleted max element " + h.removeMax());
            //h.print();
            System.out.println();
        }
        System.out.println(h);

        // test initialize
        Comparable[] z = new Comparable[30];
        for (int i = 1; i < 30; i++)
            z[inew Integer(i);
        MinMaxHeap mh = new MinMaxHeap(30);
        mh.initialize(z, 29);
        System.out.println("Our Min-Max Heap is");
        //mh.print();
        System.out.println(mh);

    }
}