20-CS-122-001 Computer Science II Spring 2012
Mergesort: function pointers

Virtual functions, classes, inheritance, lists, queues, stacks, applications

   
// Simple class for testing purposes
class LongObject {
   long number;
   
   public LongObject (long n) { number = n; }
   public long valueOf() { return number; }
}

interface Display {
   public void display (Object obj);
}

// Function used to display LongObject objects
class LOdisplay implements Display {
   public void display (Object obj) {
      if (obj == null)
         System.out.print("(nil)");
      else
         System.out.print (((LongObject)(obj)).valueOf() + " ");
   }
}

interface Compare {
   public int compare(Object x, Object y);
}

// LOompare:
//   Assume x and y are pointers to pointers of LongObjects
//   Returns 0 if values are equal, -1 if *x < *y and, 1 if *x > *y
class LOcompare implements Compare {
   public int compare(Object x, Object y) {
      if (x == null || y == null) {
         System.out.println("Error: an object is NULL");
         System.exit (0);
      }

      if (((LongObject)x).valueOf() <  ((LongObject)y).valueOf()) return -1;
      if (((LongObject)x).valueOf() == ((LongObject)y).valueOf()) return 0;
      return 1;
   }
}

class Cell {
   Object object;
   Cell cell;

   Cell(Object obj, Cell lst) {
      object = obj;
      cell = lst;
   }
}

class List {
   Cell tail;
   Display disp_object;
   Compare comp_object;

   public List (Display d, Compare c) {
      tail = null;
      disp_object = d;
      comp_object = c;
   }
   
   void push (Object t) {
      if (tail == null) {
         tail = new Cell(t, null);
         tail.cell = tail;
      } else
         tail.cell = new Cell(t, tail.cell);
   }

   // Only return a pointer to the first object in the list.
   // Do not remove it.
   Object peek() {
      if (tail == null) return null;
      return tail.cell.object;
   }

   // Return a pointer to the first object in the list.
   // Remove the first object.
   Object pop() {
      if (tail == null) return null;
      Cell ptr = tail.cell;
      Object t = ptr.object;
      if (ptr != tail)
         tail.cell = ptr.cell;
      else
         tail = null;
      return t;
   }

   // Display identities of all objects in list (ordered first to last).
   void display() {
      if (tail == null) {
         System.out.print("(empty)");
         return;
      }
      for (Cell t = tail.cell ; t != tail ; t = t.cell)
         disp_object.display(t.object);
      disp_object.display(tail.object);
   }

   // Return true if list is empty, otherwise false.
   boolean empty() { return tail == null; }

   // Return true if this list has at most one element, otherwise false.
   boolean oneElement() {
      return tail == null || tail.cell == tail;
   }

   // Given empty List object l1, transfer every other object in
   // this's list into l1.
   void splitList (List l1) {
      Object v1, v2 = null;
      boolean flag = true;

      if (empty()) return;
      v1 = pop();
      if (empty()) flag = false; else v2 = pop();
      splitList(l1);
      l1.push(v1);
      if (flag) push(v2);
   }

   // Assume this's List objects are stored in increasing "order"
   // and objects of List q2 are stored in increasing "order" (as
   // determined by comp_object).  The result of this function is
   // to adjust this's List so it contains all its old objects plus
   // all of q2's objects, and all the objects of this are in
   // increasing "order."
   List merge(List q2) {
      Object v1, v2, v;
      List q;

      if (empty()) return q2;
      if (q2.empty()) return this;

      v1 = peek();
      v2 = q2.peek();
      if (comp_object.compare(v1, v2) == -1) {
         v = pop();
         q = merge(q2);
         q.push(v);
         return q;
      } else {
         v = q2.pop();
         q = merge(q2);
         q.push(v);
         return q;
      }
   }

   // Suppose this contains a List of objects that are "orderable" by
   // by means of "comp_object."  Then the mergeSort function rearranges all
   // of these objects so they are in "order" with respect to "comp_object."
   List mergeSort() {
      List tmp = new List(new LOdisplay(), new LOcompare());
      
      if (oneElement()) return this;
      splitList(tmp);
      mergeSort();
      tmp.mergeSort();
      tail = merge(tmp).tail;
      return this;
   }
}

public class mrgsrt {
   public static void main(String args[]) {
      List l1 = new List(new LOdisplay(), new LOcompare());
      List l2 = new List(new LOdisplay(), new LOcompare());

      l1.push(new LongObject(26));
      l1.push(new LongObject(13));
      l1.push(new LongObject(8));
      l1.push(new LongObject(3));
      l1.push(new LongObject(1));

      l2.push(new LongObject(54));
      l2.push(new LongObject(36));
      l2.push(new LongObject(33));
      l2.push(new LongObject(21));
      l2.push(new LongObject(19));
      l2.push(new LongObject(11));
      l2.push(new LongObject(7));
      l2.push(new LongObject(2));

      System.out.print("\nFirst increasing list: \t");
      l1.display();
      System.out.print("\nSecond increasing list:\t");
      l2.display();

      List l3 = l1.merge(l2);
      System.out.print("\n\nMerge of two lists: ");
      l3.display();

      List l6 = new List(new LOdisplay(), new LOcompare());
      l6.push(new LongObject(33));
      l6.push(new LongObject(3));
      l6.push(new LongObject(21));
      l6.push(new LongObject(11));
      l6.push(new LongObject(7));
      l6.push(new LongObject(13));
      l6.push(new LongObject(2));
      l6.push(new LongObject(36));
      l6.push(new LongObject(54));
      l6.push(new LongObject(26));
      l6.push(new LongObject(1));
      l6.push(new LongObject(19));
      l6.push(new LongObject(8));
      System.out.print("\n\nAnother list: \t");
      l6.display();
      l6.mergeSort();
      System.out.print("\nMergeSort: \t");
      l6.display();
      System.out.println();
   }
}