CSci2110 - Problem Set 2

Due: Thursday Feb. 6th by 11:59pm

Question 1: Design and implement your own reusable implementations of the stack and queue ADTs in Java. The purpose of this question simply is to help you get the feel for the design of reusable classes. Thus the actual data structure programming is fairly straightforward, and you have been given most of the structure of the code. Reading the textbook carefully will help you greatly. The textbook describes a doubly-ended queue, which is often called a deque. The interface for a deque is the following (which is slightly different than the one given in the book):
public interface Deque {
   public int size();
   public boolean isEmpty();
   public void insertFirst(Object o);
   public void insertLast(Object o);
   public Object removeFirst() throws EmptyStructureException;
   public Object removeLast() throws EmptyStructureException;
   public Object firstElement() throws EmptyStructureException;
   public Object lastElement() throws EmptyStructureException;
}

Put this interface into a file called Deque.java. Using this interface, then, write two deque implementations: one that uses an array and one that uses a linked list. These should go into files ArrayDeque.java and LinkedListDeque.java, respectively. For more information about interfaces in Java, please see the textbook.

public class ArrayDeque implements Deque {
   ArrayDeque(int maxSize) { ... }
   ...
}

public class LinkedListDeque implements Deque {
   LinkedListDeque() { ... }
   ...
}

Thus, you need to create a class ArrayDeque, which implements the Deque interface using an array, and a class LinkedListDeque, which implements the Deque interface using a linked list. You may use classes from the Java Utilities package, but not any other libraries. Also, your ArrayDeque class should have a constructor, ArrayDeque(int maxSize), which creates an array with capacity cap, and your LinkedListDeque class should have a constructor, LinkedListDeque(), which initializes the linked list. The classes ArrayDeque and LinkedListDeque should then implement each of the methods defined in the Deque interface.

You'll need something to do in the case that a dequeue method is invoked when the deque is empty, or, in the case of the array implementation, when an insert method is invoked and the deque is full. Put (or download) the following exceptions in files EmptyStructureException.java and FullStructureException.java, respectively. Then you can throw new EmptyStructureException(), for example. See the textbook for more information about exceptions.

public class EmptyStructureException extends RuntimeException {
   public EmptyStructureException() { super(); }
   public EmptyStructureException(String s) { super(s); }
}

public class FullStructureException extends RuntimeException {
   public FullStructureException() { super(); }
   public FullStructureException(String s) { super(s); }
}

Now we can write simple adapter classes for our generic Deque interface to provide the stack and queue ADTs. The code for DequeStack already is filled in.

public class DequeStack implements Stack {
   Deque deque;
   DequeStack(Deque o) { deque = o; }
   public int size() { return deque.size(); }
   public boolean isEmpty() { return deque.isEmpty(); }
   public Object top() { return deque.lastElement(); }
   public Object pop() { return deque.removeLast(); }
   public void push(Object o) { deque.insertLast(o); }
}

public class DequeQueue implements Queue {
   ...
   public int size() { ... }
   public boolean isEmpty() { ... }
   public Object front() { ... }
   public void enqueue(Object o) { ... }
   public Object dequeue() { ... }
}

Thus we can instantiate an array-based stack of at most twelve elements with the code fragment

   DequeStack stack = new DequeStack(new ArrayDeque(12));

This demonstrates a powerful technique of code reuse, and you will have created a number of classes that you can reuse in future programs.

Be sure to test your new classes well.

Question 2a: Write a Java program that has a Polygon interface, which has abstract methods, area( ), and perimeter( ). Implement classes for Triangle, and Quadrilateral, which implement this interface, with the obvious meanings for the area( ) and perimeter( ) methods. Also implement classes IsoscelesTriangleRectangle, and Square, which have the appropriate inheritance relationships, and implement the polygon interface. All of your shape classes should inheret from a simple2DPollygon class. Finally, write a tester class, which creates simple2DPolygon of the various types, and then output their area and perimeter. Try to design the constructors so all valid instances of these polygons (in the positive Eurclidean quadrant) can be created and no invalid one's can be.

BONUS Questions

Implement one or more of the following methods for your shape classes:

Note: No late assignments will be accepted. Discuss ideas with your friends, but write and hand in your own code. Plagiarism will be dealt with severely.