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

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

Prev      Next      Lectures      Source      Java Version

#include <fstream>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

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

// Function used to display LongObject objects
void LOdisplay (void *obj) {
   if (obj == NULL)
      cout << "(nil) ";
   else
      cout << ((LongObject *)(obj))->valueOf() << " ";
}

// LOcompare:
//   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
int LOcompare(const void *x, const void *y) {
   if (x == NULL || y == NULL) {
      cout << "Error: an object is NULL\n";
      exit (0);
   }

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

class Cell {
friend class List;
   
   void *object;
   Cell *cell;

 public:
   Cell(void *obj, Cell *lst) {
      object = obj;
      cell = lst;
   }
};

class List {
   Cell *tail;
   void (*dispfunc) (void *);
   int  (*compfunc) (const void *x, const void *y);

public:
   List (void (*d)(void *), int (*c)(const void *x, const void *y)) {
      tail = NULL;
      dispfunc = d;
      compfunc = c;
   }
   
   void push (void *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.
   void *peek() {
      if (tail == NULL) return NULL;
      return tail->cell->object;
   }

   // Return a pointer to the first object in the list.
   // Remove the first object.
   void *pop() {
      if (tail == NULL) return NULL;
      Cell *ptr = tail->cell;
      void *t = ptr->object;
      if (ptr != tail)
         tail->cell = ptr->cell;
      else
         tail = NULL;
      delete ptr;
      return t;
   }

   // Display identities of all objects in list (ordered first to last).
   void display() {
      Cell *t;
      if (tail == NULL) {
         cout << "(empty)";
         return;
      }
      for (t = tail->cell ; t != tail ; t = t->cell)
         (dispfunc)(t->object);
      (dispfunc)(tail->object);
   }

   // Return 1 if list is empty, otherwise 0.
   int empty() { return tail == NULL; }

   // Return 1 if list has at most one element, otherwise 0.
   int 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) {
      void *v1, *v2;
      int flag = 1;

      if (empty()) return;
      v1 = pop();
      if (empty()) flag = 0; 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 compfunc).  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) {
      void *v1, *v2, *v;
      List *q;

      if (empty()) return q2;
      if (q2->empty()) return this;

      v1 = peek();
      v2 = q2->peek();
      if ((compfunc)(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 "compfunc."  Then the mergeSort function rearranges all
   // of these objects so they are in "order" with respect to "compfunc."
   // (deletions are not taken care of).
   List *mergeSort() {
      List *tmp = new List(LOdisplay, LOcompare);
      
      if (oneElement()) return this;
      splitList(tmp);
      mergeSort();
      tmp->mergeSort();
      tail = merge(tmp)->tail;
      return this;
   }
};

int main() {
   List *l1 = new List(LOdisplay, LOcompare);
   List *l2 = new List(LOdisplay, 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));

   cout << "\nFirst increasing list: \t";
   l1->display();
   cout << "\nSecond increasing list:\t";
   l2->display();

   List *l3 = l1->merge(l2);
   cout << "\n\nMerge of two lists: ";
   l3->display();

   List *l6 = new List(LOdisplay, 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));
   cout << "\n\nAnother list: \t";
   l6->display();
   l6->mergeSort();
   cout << "\nMergeSort: \t";
   l6->display();
   cout << "\n";
}