20-CS-122-001 Computer Science II Spring 2012
Lists and Arrays: Checking Network Redundancy

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

    Java version

// A collection of cities and roads connecting them is called
// a network.  A network is redundant if there exists a pair of
// cities for which there are at least two different ways to travel
// between them.  This code finds whether a given network is redundant.
// It outputs 1 if yes and 0 otherwise. 

#include <fstream.h>
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>

int max (int a, int b) { if (a < b) return b; else return a; }

void intdisplay(void *t) { cout << *(int *)t << " "; }

// Array class protects against index out of bounds errors
class Array {
  int rows;
  int cols;
  int *array;

public:
  Array (int r, int c) {
     int i;
     rows=r;
     cols=c;
     array = new int[r*c];
     for (i=0 ; i < r*c ; i++) array[i] = 0;
  }

  Array (int c) {
     int i;
     rows=1;
     cols=c;
     array = new int[c];
     for (i=0 ; i < c ; i++) array[i] = 0;
  }

  int get(int i, int j) {
     if (i < 0 || i > rows) return 0;
     if (j < 0 || j > cols) return 0;
     return array[i*cols+j];
  }

  int get(int i) {
     if (i < 0 || i > cols) return 0;
     return array[i];
  }

  void put(int i, int j, int k) {
     if (i >= 0 && i <= rows && j >= 0 && j <= cols)
        array[i*cols+j] = k;
  }

  void put(int i, int k) {
     if (i >= 0 && i <= cols) array[i] = k;
  }

  ~Array() { delete array; }
};

// Objects of cell class hold actually interesting objects, such
// as cities, in a linked list.
class Cell {
friend class Queue;

   void *item;
   Cell *next;

public:
   Cell(void *ptr, Cell *lst) {
      item = ptr;
      next = lst;
   }
};

// Queue class puts together cells to make a queue.
class Queue {
   Cell *head;
   Cell *tail;
   void (* dispfn)(void *);

public:
   Queue(void (* d)(void *)) {
      dispfn = d;
      head = NULL;
      tail = NULL;
   }

   void enqueue(void *t) {
      Cell *ptr;
      if (t == NULL) return;
      Cell *h = new Cell(t, NULL);
      if (head == NULL)
         head = h;
      else
         tail->next = h;
      tail = h;
   }

   void *dequeue() {
      if (head == NULL) return NULL;
      void *ptr = head;
      void *t = head->item;
      head = head->next;
      delete ptr;
      if (head == NULL) tail = NULL;
      return t;
   }

   void display() {
     if (head == NULL) { cout << "(empty)\n";  return; }
     for (Cell *t=head ; t != NULL ; t=t->next) (dispfn)(t->item);
     cout << "\n";
   }

   int empty()  {  return head == NULL;  }
};

// City objects are what we are primarily interested in here.
class City {
   int cty;
   int prnt;

public:
   City (int c, int p) { cty=c; prnt=p; }
   int parent()  { return prnt; }
   int city()    { return cty; }
};

/***--------------------------------------------------***/
/*** Redundancy:                                      ***/
/***   Input:  A network (n by n array of 0-1 values) ***/
/***   Output: 1 if network is redundant              ***/
/***           0 otherwise                            ***/
/*** Checks network links for redundant connections   ***/
/***--------------------------------------------------***/
int redundancy(Array *links, int cities) {
   Queue *s = new Queue(intdisplay);
   Array *visited = new Array(cities+1);
   City  *current;
   int i;

   s->enqueue (new City(0,-1));
   s->display();
   while (!s->empty()) {
      current = (City *)s->dequeue();
      s->display();
      if (visited->get(current->city())) continue;
      visited->put(current->city(), 1);
      for (i=0 ; i<=cities ; i++) {
         if (!links->get(current->city(),i) || current->city() == i) continue;
         if (!visited->get(i)) {
            s->enqueue(new City(i, current->city()));
            s->display();
         } else if (i != current->parent()) return 1;
      }
   }
   return 0;
}

#define MAX_CITIES 200

int main(int argc, char **argv) {
   Array *links = new Array(MAX_CITIES, MAX_CITIES);
   int city1, city2, cities=0;

   if (argc != 2) exit(0);
   fstream fin(argv[1], ios::in);
   while (fin >> city1 >> city2) {
      links->put(city1, city2, 1);
      cities = max(max(cities, city1), city2);
   }
   fin.close();

   int result = redundancy(links, cities);
   cout << "<<" << result << ">>\n";
   return 1;
}

// Sample Output:
//   0 
//   (empty)
//   3 
//   3 4 
//   3 4 5 
//   4 5 
//   4 5 2 
//   4 5 2 4 
//   4 5 2 4 5 
//   5 2 4 5 
//   <<1>>

// On Input: 
//   0 3
//   0 4
//   0 5
//   1 2
//   1 5
//   2 1
//   2 3
//   2 6
//   3 0
//   3 2
//   3 4
//   3 5
//   4 0
//   4 3
//   4 6
//   5 0
//   5 1
//   5 3
//   6 2
//   6 4