interface Bag<E> {
   void put(E obj);
   E get(); //extract some object
   boolean isEmpty();
}

interface PriorityQueue<E extends Comparable> extends Bag<E> {}

class PQ<E extends Comparable> extends java.util.Vector<E> implements PriorityQueue<E> {
   
   public void put(E obj) {
      add(obj);
      rotateUp(size() - 1);
   }
   
   public E get() {
      if (isEmpty()) throw new java.util.NoSuchElementException();
      E temp = elementAt(0);
      setElementAt(elementAt(size() - 1), 0);
      setSize(size() - 1);
      rotateDown(0);
      return temp;
   }
   
   private void rotateUp(int index) {
      if (index == 0) return;
      int parent = (index - 1)/2;
      if (elementAt(parent).compareTo(elementAt(index)) <= 0) return;
      swap(index, parent);
      rotateUp(parent);
   }
   
   private void rotateDown(int index) {
      int child = 2*(index + 1); //right child
      if (child >= size() || elementAt(child - 1).compareTo(elementAt(child)) < 0) child -= 1;
      if (child >= size()) return;
      if (elementAt(index).compareTo(elementAt(child)) <= 0) return;
      swap(index, child);
      rotateDown(child);
   }
   
   private void swap(int index1, int index2) {
      E temp = elementAt(index1);
      setElementAt(elementAt(index2), index1);
      setElementAt(temp, index2);
   }      
}

class HeapSort {
   public static void main(String[] args) {
      Integer[] a = new Integer[20];
      java.util.Random random = new java.util.Random();
      for (int i = 0; i < a.length; i++) {
         a[i] = new Integer(random.nextInt(100));
         System.out.print(a[i] + " ");
      }
      System.out.println();
      heapSort(a);
      for (Integer x : a) {
         System.out.print(x + " ");
      }
      System.out.println();
   }
   
   public static void heapSort(Comparable[] a) {
      PriorityQueue<Comparable> pq = new PQ<Comparable>();
      for (Comparable x : a) { pq.put(x); }
      for (int i = 0; i < a.length; i++) { a[i] = pq.get(); }
   }
}
