Select a Chapter: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Back to the Main Page
Chapter Fourteen listings: 15 classes and 2 interfaces

public interface StackADT            // not in the Sun library
{
     /** Tell whether the stack has no more elements. */

     public boolean isEmpty();


     /** Return the value that pop would give, without modifying
      *  the stack.  Throw an Exception if the stack is empty. */

     public Object peekTop();


     /** Remove and return the value that has been in the stack the 
      *  least time.  Throw an Exception if the stack is empty. */

     public Object pop();

 
    /** Add the given value to the stack. */

     public void push (Object ob); 
} 


public interface QueueADT            // not in the Sun library
{
     /** Tell whether the queue has no more elements. */

     public boolean isEmpty();


     /** Return the value that dequeue would give without modifying
      *  the queue.  Throw an Exception if the queue is empty. */

     public Object peekFront();


     /** Remove and return the value that has been in the queue the 
      *  most time.  Throw an Exception if the queue is empty. */

     public Object dequeue();


     /** Add the given value to the queue. */

     public void enqueue (Object ob); 
} 


public class StackAndQueueTester
{

     /** For test purposes:  Create a stack of 5 values,
      *  print it, reverse the order, then print the result. */

     public static void main (String[] args)
     {    ArrayStack stack = new ArrayStack();
          for (int k = 0;  k < 5;  k++)
               stack.push (new Double (Math.random()));
          System.out.println ("Before reversing the stack: \n"
                              + stack.toString());
          QuackOp.reverse (stack);
          System.out.println ("\nAfter reversing the stack: \n"
                              + stack.toString());
     }    //======================
}


public class QuackOp // independent methods for queues and stacks
{
     /** Precondition for these methods:  
      *  The stack and queue parameters are not null. */


     /** Return the numeric value of the given postfix expression. */

     public static int evaluatePostfix (QueueADT queue)
     {    StackADT stack = new ArrayStack();
          while ( ! queue.isEmpty())
          {    Object data = queue.dequeue();
               if (data instanceof Integer)
                    stack.push (data);
               else
               {    char operator = ((Character) data).charValue();
                    int second = ((Integer) stack.pop()).intValue();
                    int first = ((Integer) stack.pop()).intValue();
                    if (operator == '+')
                         stack.push (new Integer (first + second));
                    else if (operator == '-')
                         stack.push (new Integer (first - second));
                    //etc.
               }
          }
          int valueToReturn = ((Integer) stack.pop()).intValue();
          if ( ! stack.isEmpty()) 
               throw new RuntimeException ("too many values");
          return valueToReturn;
     }    //======================


     /** Return a new queue containing the postfix equivalent of
      *  the infix expression in the parameter. */

     public static QueueADT fromInfixToPostfix (QueueADT queue)
     {    QueueADT postfix = new ArrayQueue();
          StackADT stack = new ArrayStack();
          while ( ! queue.isEmpty())
          {    Object data = queue.dequeue();
               if (data instanceof Integer)
                    postfix.enqueue (data);
               else
               {    char nonNumber = ((Character) data).charValue();
                    if (nonNumber == ')')
                         postfix.enqueue (stack.pop());
                    else if (nonNumber != '(')  // ignore left paren
                         stack.push (data);
               }
          }
          return postfix;
     }    //======================


     /** Reverse the order of the elements on the given stack. */

     public static void reverse (StackADT stack)
     {    QueueADT queue = new ArrayQueue();
          while ( ! stack.isEmpty())
               queue.enqueue (stack.pop());
          while ( ! queue.isEmpty())
               stack.push (queue.dequeue());
     }    //======================


     /** Remove and return the second value on the stack.  If the
      *  stack has less than 2 elements, simply return null. */

     public static Object removeSecond (StackADT stack)
     {    if (stack.isEmpty())
               return null;
          Object first = stack.pop();
          Object valueToReturn = stack.isEmpty()  ?  null : stack.pop();
          stack.push (first);
          return valueToReturn;
     }    //======================


     /** Remove all elements on the stack down to but not including
      *  the given object. */

     public static void removeDownTo (StackADT stack, Object ob)
     {    if (ob == null)
          {    while ( ! stack.isEmpty() && stack.peekTop() != null)
                    stack.pop();
          }
          else
          {    while ( ! stack.isEmpty() && ! ob.equals (stack.peekTop())) 
                    stack.pop();
          }
     }    //======================


     /** Remove and return the second value on the queue.  If the
      *  queue has less than 2 elements, simply return null. */

     public static Object removeSecond (QueueADT queue)
     {    if (queue.isEmpty())
               return null;
          Object first = queue.dequeue();
          Object valueToReturn = queue.isEmpty() ? null : queue.dequeue();
          Object endMarker = new Double (0.0); // anything brand-new works
          queue.enqueue (endMarker);
          queue.enqueue (first);
          while (queue.peekFront() != endMarker)
               queue.enqueue (queue.dequeue());
          queue.dequeue();  // remove endMarker, so first is now at front
          return valueToReturn;
     }    //======================
}


public class ArrayStack implements StackADT
{
     private Object[] itsItem = new Object [10];
     private int itsSize = 0;


     public boolean isEmpty()
     {    return itsSize == 0;
     }    //======================


     public Object peekTop()
     {    if (isEmpty())
               throw new IllegalStateException ("stack is empty");
          return itsItem[itsSize - 1];
     }    //======================


     public Object pop()
     {    if (isEmpty())
               throw new IllegalStateException ("stack is empty");
          itsSize--;
          return itsItem[itsSize];
     }    //======================


     public void push (Object ob) 
     {    if (itsSize == itsItem.length)
          {    Object[] toDiscard = itsItem;
               itsItem = new Object [2 * itsSize];
               for (int k = 0;  k < itsSize;  k++)
                    itsItem[k] = toDiscard[k];
          }
          itsItem[itsSize] = ob;
          itsSize++;
     }    //======================


     /** Exercise:  Remove all elements in the stack that are below
      *  the parameter.  No effect if it is not in the stack. */

     public void removeBelow (Object ob)
     {    int spot = itsSize - 1;
          if (ob == null)
          {    while (spot > 0 &&  itsItem[spot] != null)
                    spot--;
          }
          else
          {    while (spot > 0 &&  ! ob.equals (itsItem[spot]))
                    spot--;
          }
          if (spot > 0)
          {    for (int k = spot;  k < itsSize;  k++)
                    itsItem[k - spot] = itsItem[k];
               itsSize -= spot;
          }
     }    //======================


     public boolean equals (Object ob)
     {    if ( ! (ob instanceof ArrayStack) 
                        || ((ArrayStack) ob).itsSize != this.itsSize)
               return false;
          ArrayStack given = (ArrayStack) ob;   // for efficiency
          for (int k = 0;  k < this.itsSize;  k++)
          {    if ( ! this.itsItem[k].equals (given.itsItem[k]))
                    return false;
          }
          return true;
     }    //======================


     public String toString()
     {    String valueToReturn = "";
          for (int k = 0;  k < itsSize;  k++)
               valueToReturn += '\t' + itsItem[k].toString();
          return valueToReturn;
     }    //======================
}     


public class ArrayQueue implements QueueADT
{
     private Object[] itsItem = new Object [10];
     private int itsFront = 0;  // location of front element, if any 
     private int itsRear = -1;  // location of rear element, if any 


     public boolean isEmpty()
     {    return itsRear == itsFront - 1;
     }    //======================


     public Object peekFront()
     {    if (isEmpty())
               throw new IllegalStateException ("queue is empty");
          return itsItem[itsFront];
     }    //======================


     public Object dequeue()
     {    if (isEmpty())
               throw new IllegalStateException ("queue is empty");
          itsFront++;
          return itsItem[itsFront - 1];
     }    //======================


     public void enqueue (Object ob) 
     {    if (itsRear == itsItem.length - 1)
               adjustTheArray();
          itsRear++;
          itsItem[itsRear] = ob;
     }    //======================


     /** Shift elements to the front if the array is less than
      *  three-quarters full, otherwise transfer to a bigger array.
      *  Precondition:  itsRear is the last index in the array. */

     private void adjustTheArray()
     {    if (itsFront > itsRear / 4)
          {    itsRear -= itsFront;
               for (int k = 0;  k <= itsRear;  k++)
                    itsItem[k] = itsItem[k + itsFront];
               itsFront = 0;
          }
          else
          {    Object[] toDiscard = itsItem;
               itsItem = new Object [2 * itsRear];
               for (int k = 0;  k <= itsRear;  k++)
                    itsItem[k] = toDiscard[k];
          }  // automatic garbage collection gets rid of toDiscard
     }    //======================


     public int size()
     {    return itsRear - itsFront + 1;
     }    //======================


     public String toString()
     {    String valueToReturn = "";
          for (int k = itsFront;  k <= itsRear;  k++)
               valueToReturn += '\t' + itsItem[k].toString();
          return valueToReturn;
     }    //======================
}     


public class Node 
{
     private Object itsData;
     private Node itsNext;

     public Node (Object data, Node next)
     {    itsData = data;
          itsNext = next;
     }    //======================


     /** Return the data attribute of the Node. */

     public Object getValue()
     {    return itsData;
     }    //======================


     /** Return the next attribute of the Node. */

     public Node getNext()
     {    return itsNext;
     }    //======================


     /** Replace the data attribute. */

     public void setValue (Object data)
     {    itsData = data;
     }    //======================


     /** Replace the next attribute. */

     public void setNext (Node next)
     {    itsNext = next;
     }    //======================
}


public class NodeStack implements StackADT
{
     private Node itsTop = null;


     public boolean isEmpty()
     {    return itsTop == null;
     }    //======================


     public Object peekTop()
     {    if (isEmpty())
               throw new IllegalStateException ("stack is empty");
          return itsTop.getValue();
     }    //======================


     public Object pop()
     {    if (isEmpty())
               throw new IllegalStateException ("stack is empty");
          Node toDiscard = itsTop;
          itsTop = itsTop.getNext();
          return toDiscard.getValue();
     }    //======================


     public void push (Object ob) 
     {    itsTop = new Node (ob, itsTop);
     }    //======================
}     


public class NodeQueue implements QueueADT
{
     private Node itsFront = null;
     private Node itsRear;


     /** Tell whether the queue has no more elements. */

     public boolean isEmpty()
     {    return itsFront == null;
     }    //======================


     /** Return the value that dequeue would give without modifying
      *  the queue.  Throw an Exception if the queue is empty. */

     public Object peekFront()
     {    if (isEmpty())
               throw new IllegalStateException ("queue is empty");
          return itsFront.getValue();
     }    //======================


     /** Remove and return the value that has been in the queue the 
      *  most time.  Throw an Exception if the queue is empty. */

     public Object dequeue()
     {    if (isEmpty())
               throw new IllegalStateException ("queue is empty");
          Node toDiscard = itsFront;
          itsFront = itsFront.getNext();
          return toDiscard.getValue();
     }    //======================


     /** Add the given value to the queue. */

     public void enqueue (Object ob) 
     {    Node toBeAdded = new Node (ob, null);
          if (isEmpty())
               itsFront = toBeAdded;
          else
               itsRear.setNext (toBeAdded);
          itsRear = toBeAdded; 
     }    //======================


     /** Return the number of elements in the queue. */

     public int size()
     {    int count = 0;
          for (Node p = itsFront;  p != null;  p = p.getNext())
               count++;
          return count;
     }

     /** Add all the values in the queue parameter to the rear of
      *  the executor.  Precondition:  queue is not null. */

     public void append (NodeQueue queue)
     {    if ( ! queue.isEmpty())
          {    if (this.isEmpty())
                    this.itsFront = queue.itsFront;
               else
                    this.itsRear.setNext (queue.itsFront);
               this.itsRear = queue.itsRear;
               queue.itsFront = null;
          }
     }    //======================
}    


public abstract class ListADT implements StackADT
{
     /** Return the portion of this list that contains all values
          after the first value. Return null if this list is empty.*/

     public abstract ListADT theRest();


     /** Replace the data value at the front of the list by ob.
           No effect if this list is empty. */

     public abstract void setTop (Object ob);


// The four StackADT methods (descriptions are in Listing 14.1)

     public final boolean isEmpty()
     {    return theRest() == null;
     }    //======================

     public abstract Object peekTop();

     public abstract Object pop();

     public abstract void push (Object ob);


     /** Add the given data value at the end of this list. */

     public void addLast (Object ob)
     {    if (this.isEmpty())
               this.push (ob);
          else
               theRest().addLast (ob);
     }    //======================


     /** Return the number of data values in this list. */

     public int size() 
     {    return this.isEmpty() ? 0 : 1 + theRest().size();
     }    //======================


     /** Remove and return the data value at the given index (zero-
           based). Throw an Exception if no data is at that index. */

     public Object remove (int index) 
     {    return index == 0 ? pop() : theRest().remove (index-1); //1
     }    //======================


     /** Insert the data value at the given index (zero-based).
           Throw an Exception if index < 0 or index > size(). */

     public void add (int index, Object ob) 
     {    if (index == 0)                                        //2
               push (ob);                                        //3
          else                                                   //4
               theRest().add (index - 1, ob);                    //5
     }    //======================


     /** Return the last data value in this ListADT.
           Throw an Exception if the ListADT is empty. */

     public Object getLast()
     {    return theRest().isEmpty() ? peekTop()                  //6
                                     : theRest().getLast();       //7
     }    //======================


     /** Return the lowest index where ob occurs.  
           Return -1 if ob does not occur anywhere in the list. */

     public int indexOf (Object ob)
     {    return ob == null ? indexOfNull (0) : indexOf (0, ob); //1
     }    //======================


     private int indexOfNull (int index)
     {    if (isEmpty())                                         //2
               return -1;                                        //3
          else if (null == peekTop())                            //4
               return index;                                     //5
          else                                                   //6
               return theRest().indexOfNull (index + 1);         //7
     }    //======================


     // Precondition:  ob is not null.

     private int indexOf (int index, Object ob)
     {    if (isEmpty())                                         //8
               return -1;                                        //9
          else if (ob.equals (peekTop()))                        //10
               return index;                                     //11
          else                                                   //12
               return theRest().indexOf (index + 1, ob);         //13
     }    //======================


     /** Tell whether the parameter is one of the data values
           in the list. */

     public boolean contains (Object ob) 
     {    return indexOf (ob) != -1;                             //14
     }    //======================


     /* These ListADT methods are described and coded in the exercises */

     public void clear()         // remove all data, leave it empty
     {    while ( ! isEmpty())
               pop();
     }    //======================


     public void copyTo (ListADT par)  // insert all at the front of par 
     {    if ( ! this.isEmpty())
          {    par.push (this.peekTop ());
               this.theRest().copyTo (par.theRest());
          }
     }    //======================


     public Object get (int index)       // return the data there
     {    return (index == 0)  ?  peekTop()  :  theRest().get (index - 1);
     }    //======================


     public void setLast (Object ob)
     {    if (theRest().isEmpty())
               setTop (ob);
          else
               theRest().setLast (ob);
     }    //======================


     public boolean equals (ListADT that)
     {    if (this.isEmpty())
               return that.isEmpty();  // i.e., both are empty
          else if (that.isEmpty())
               return false;
          else
               return this.peekTop().equals (that.peekTop()) 
                         && this.theRest().equals (that.theRest());
     }    //======================


     /* These ListADT methods are only described in the exercises
     public void addAll (ListADT par)  // append all at its end
     public Object[] toArray (Object[] par)  // copy it to an array
     public void set (int index, Object ob)  // replace that data
     public Object removeLast()    // remove the last and return it
     public boolean remove (Object ob)   // remove it if you can
     public int lastIndexOf (Object ob)
     public String toString()       // return the String equivalent
     public boolean containsAll (ListADT that)     */


     /** Add the given value to the list before the first data
           value that is greater-equal to it, using compareTo.  
           Add it at the end of the list if there is no such value.
           Precondition:  ob is non-null and Comparable to all
           data values currently in the list. */

     public void insertInOrder (Comparable ob)
     {    if (this.isEmpty() || ob.compareTo (peekTop()) <= 0)
               this.push (ob);
          else
               theRest().insertInOrder (ob);
     }    //======================


     /** Rearrange the data values to be in ascending order.  Throw
           an Exception unless all values are mutually Comparable. */

     public void insertionSort()
     {    if ( ! this.isEmpty())
          {    theRest().insertionSort();
               this.insertInOrder ((Comparable) this.pop());
          }
     }    //======================


     public Object removeSmallest()
     {    Comparable smallestSoFar = (Comparable) this.peekTop();
          ListADT spot = this;
          for (ListADT p = this.theRest();  ! p.isEmpty();  p = p.theRest())
          {    if (smallestSoFar.compareTo (p.peekTop()) > 0)
               {    smallestSoFar = (Comparable) p.peekTop();
                    spot = p;
               }
          }
          return spot.pop();   // which is in fact smallestSoFar
     }    //======================
}


public class NodeList extends ListADT
{
     private Object itsData = null;
     private NodeList itsNext = null;


     public ListADT theRest()
     {    return itsNext;                                        //1
     }    //======================


     public void setTop (Object ob)
     {    itsData = ob;                                          //2
     }    //======================


     public Object peekTop()
     {    if (itsNext == null)  // so it represents an empty list//3
               throw new IllegalStateException ("nothing there");//4
          return itsData;                                        //5
     }    //======================


     public void push (Object ob)
     {    NodeList toAdd = new NodeList();                       //6
          toAdd.itsData = this.itsData;                          //7
          toAdd.itsNext = this.itsNext;                          //8
          this.itsData = ob;                                     //9
          this.itsNext = toAdd;                                  //10
     }    //======================


     public Object pop()
     {    Object valueToReturn = this.itsData;                   //11
          NodeList toDiscard = this.itsNext;                     //12
          this.itsData = toDiscard.itsData;                      //13
          this.itsNext = toDiscard.itsNext;                      //14
          toDiscard.itsNext = null;   // make this list empty    //15
          return valueToReturn;                                  //16
     }    //======================
}     


public class CardList extends NodeList
{
     private java.util.Random randy = new java.util.Random();


     /** Put the numToDo data values in a random order.  
           Throw an Exception if numToDo > this.size(). */

     public void shuffleAllCards (int numToDo)
     {    ListADT list = this;
          for ( ;  numToDo >= 2;  numToDo--)
          {    list.push (list.remove (randy.nextInt (numToDo)));
               list = list.theRest();
          }
     }    //======================


     /** Repeatedly remove the first legally-removable pair of
           cards.  Return true if this leaves the list empty, false 
           if not. Precondition: All data values are Card objects. */

     public boolean removeAllSucceeds()
     {    return this.isEmpty() || (removeTheFirstSucceeds (this)
                                    && this.removeAllSucceeds());
     }    //======================


     /** Remove the first legally-removable pair of cards from list 
           if you can.  Return false if there is no legal move. */

     private boolean removeTheFirstSucceeds (ListADT list)
     {    if (list.theRest().isEmpty()) //positioned at the last card
               return false;
          Card first = (Card) list.peekTop();
          Card second = (Card) list.theRest().peekTop();
          if (first.getRank() == second.getRank()
                        || first.getSuit() == second.getSuit())
          {    list.pop();
               list.pop();
               return true;
          }
          return removeTheFirstSucceeds (list.theRest());
     }    //======================
}     


public class DoublyLinked extends ListADT
{
     private Object itsData = null;
     private DoublyLinked itsNext = null;
     private DoublyLinked itsPrevious = null;


     /** Return the DoublyLinked object for which theRest is this
           list, if any. But return null if there is no such list. */

     public DoublyLinked theOneBefore()
     {    return itsPrevious;                                      //1
     }    //======================


     public void push (Object ob)
     {    DoublyLinked toAdd = new DoublyLinked();                 //2
          toAdd.itsData = this.itsData;                            //3
          toAdd.itsNext = this.itsNext;                            //4
          this.itsData = ob;                                       //5
          this.itsNext = toAdd;                                    //6
          toAdd.itsPrevious = this;                                //7
          if (toAdd.theRest() != null)                             //8
               ((DoublyLinked)toAdd.theRest()).itsPrevious = toAdd;//9
     }    //======================


     public Object pop()
     {    Object valueToReturn = this.itsData;                     //10
          DoublyLinked toDiscard = this.itsNext;                   //11
          this.itsData = toDiscard.itsData;                        //12
          this.itsNext = toDiscard.itsNext;                        //13
          toDiscard.itsNext = null;   // make this list empty      //14
          toDiscard.itsPrevious = null;                            //15
          if (this.theRest() != null)                              //16
               ((DoublyLinked) this.theRest()).itsPrevious = this; //17
          return valueToReturn;                                    //18
     }    //======================


     public ListADT theRest()
     {    return itsNext;                                          //1
     }    //======================


     public Object peekTop()
     {    if (itsNext == null)  // so it represents an empty list  //2
               throw new IllegalStateException ("nothing there");  //3
          return itsData;                                          //4
     }    //======================


     public void setTop (Object ob)
     {    itsData = ob;                                            //5
     }    //======================
}


public class HeaderList extends ListADT
{
     private Object itsData = null;
     private HeaderList itsNext = null;


     public ListADT theRest()
     {    return itsNext;                                          //1
     }    //======================


     public Object peekTop()        // Throws Exception if empty
     {    return itsNext.itsData;                                  //2
     }    //======================


     public void setTop (Object ob)
     {    if (itsNext != null)                                     //3
               itsNext.itsData = ob;                               //4
     }    //======================


     public void push (Object ob)
     {    HeaderList toAdd = new HeaderList();                     //5
          toAdd.itsData = ob;                                      //6
          toAdd.itsNext = this.itsNext;                            //7
          this.itsNext = toAdd;                                    //8
     }    //======================


     public Object pop()
     {    HeaderList toDiscard = this.itsNext;                     //9
          this.itsNext = toDiscard.itsNext;                        //10
          toDiscard.itsNext = null;   // make this list empty      //11
          return toDiscard.itsData;                                //12
     }    //======================
}


public class JosephusList extends NodeList
{
     /** Remove every nth one circularly until only one is left.
           Return that one.  Precondition:  The list is not empty. */

     public Object josephus (int numToCount)
     {    ListADT circle = this;
          while ( ! this.theRest().isEmpty())  // more than 1 left
               circle = popAfterGoingForward (circle, numToCount);
          return this.peekTop();
     }    //======================


     private ListADT popAfterGoingForward (ListADT circle, int num)
     {    for (int k = 0;  k < num;  k++)
          {    circle = circle.theRest();
               if (circle.isEmpty())
                    circle = this;
          }
          circle.pop();
          return circle;
     }    //======================
}


public class WebData
{
     public final int MAX;
     private WebList[] itsItem;


     public WebData (int numCategories)
     {    MAX = (numCategories > 0) ? numCategories : 1;
          itsItem = new WebList [MAX];
          for (int k = 0;  k < MAX;  k++)
               itsItem[k] = new WebList();
     }    //======================


     /** Add the given page/link association of the given category.
      *  Ignore any category outside of the range 0..MAX-1. */

     public void addLink (int category, Object page, Object link)
     {    if (page != null && category >= 0 && category < MAX)
               itsItem[category].addLink (page, link);
     }    //======================


     public void listAll (int category)
     {    if (category >= 0 && category < itsItem.length)
               itsItem[category].listAll();
     }    //======================
}


/** A WebList contains zero or more non-empty NodeList objects. 
 *  itsPrior is a reference to one of them if not null.  Each of 
 *  those NodeLists contains 1 web page followed by its links. */

public class WebList extends NodeList
{
     private ListADT itsPrior = null;


     public void addLink (Object page, Object link)
     {    if (itsPrior == null || ! itsPrior.peekTop().equals (page))
               itsPrior = findMatchEvenIfYouHaveToMakeIt (page);
          itsPrior.theRest().push (link);  // push after the page
     }    //======================


     private ListADT findMatchEvenIfYouHaveToMakeIt (Object page)
     {    ListADT pos = this;
          for ( ; ! pos.isEmpty(); pos = pos.theRest())
          {    if (((ListADT) pos.peekTop()).peekTop().equals (page))
                    return (ListADT) pos.peekTop();
          }
          ListADT toAdd = new NodeList();
          toAdd.push (page);
          pos.push (toAdd);  // putting it at the end of this WebList
          return toAdd;
     }    //======================

     public void listAll()
     {    // left as an exercise
     }    //======================
}

All information Copyright (c)1999 - Dr. William C. Jones, Jr.
Layout and Design Copyright © Psumonix, LLC. All Rights Reserved.