Soluzione 8.5

Abbiamo scritto la classe QueueByStack e la corrispondente classe di collaudo in un unico file. Valgono osservazioni speculari rispetto all'esercizio precedente.
Per quanto riguarda l'analisi delle prestazioni dei metodi di QueueByStack Per quanto riguarda la classe QueueByStackTester, la difficolta` principale sta nello scrivere il metodo compareQueues; la soluzione proposta realizza il seguente algoritmo:
public class QueueByStackTester
{   public static void main(String[] args)
    {   //creo due code (gli oggetti appartengono a classi diverse,
        //ma i riferimenti q1 e q2 sono entrambi di tipo Queue) 
        Queue q1 = new ArrayQueue();
        Queue q2 = new QueueByStack();
        //operazioni sulla prima coda
        q1.enqueue(new Integer(2));
        q1.enqueue("pippo");
        q1.getFront();
        q1.dequeue();
        q1.enqueue("pluto");
        q1.getFront();
        //operazioni (identiche) sulla seconda coda
        q2.enqueue(new Integer(2));
        q2.enqueue("pippo");
        q2.getFront();
        q2.dequeue();
        q2.enqueue("pluto");
        q2.getFront();

        if (compareQueues(q1, q2))  System.out.println("Collaudo riuscito");
        else                        System.out.println("Collaudo non riuscito");
    }
  
    //metodo statico ausiliario: confronta il contenuto delle code q1 e q2
    public static boolean compareQueues(Queue q1, Queue q2)
    {   Queue temp1 = new ArrayQueue();
        Queue temp2 = new ArrayQueue();
        boolean areEquals = true;
        while (!q1.isEmpty() && !q2.isEmpty() && areEquals)
        {   Object obj1 = q1.dequeue();
	        temp1.enqueue(obj1);
	        Object obj2 = q2.dequeue();
	        temp2.enqueue(obj2);
            // controllo che obj1 e obj2 siano o entrambi null o riferimenti 
            // ad oggetti uguali
            areEquals = (obj1 == null && obj2 == null) || 
                        (obj1 != null && obj1.equals(obj2) );
        }
        if (!q1.isEmpty() || !q2.isEmpty()) //le due code non contengono 
            areEquals = false;              //lo stesso numero di elementi

        while (!temp1.isEmpty())
            q1.enqueue(temp1.dequeue());  // ri-travasiamo i contenuti di temp1 
        while (!temp2.isEmpty())           // e temp2 nelle due code iniziali
            q2.enqueue(temp2.dequeue());

        return areEquals;
    }
}

//la classe QueueByStack: usa pile per realizzare una coda
class QueueByStack implements Queue
{
    public QueueByStack()
    {   s = new ArrayStack();
    }
  
    public void makeEmpty()
    {   s.makeEmpty();
    }
  
    public boolean isEmpty()
    {   return s.isEmpty();
    }
  
    public void enqueue(Object obj)
    {   Stack temp = new ArrayStack();
        while (!s.isEmpty())
            temp.push(s.pop());       // svuotiamo temporaneamente la pila
        s.push(obj);                  // inseriamo il nuovo oggetto
        while (!temp.isEmpty())       // re-impiliamo gli elementi
            s.push(temp.pop());       // il nuovo oggetto e' in fondo alla pila, 
    }                                 //ovvero alla fine della coda
  
    public Object getFront()
    {   try
        { return s.top(); }
        catch (EmptyStackException e)            // se la pila e' vuota...
        { throw new EmptyQueueException(); }   // ... allora la coda e' vuota
    }
  
    public Object dequeue()
    {
        try
        { return s.pop(); }
        catch (EmptyStackException e)            // se la pila e' vuota...
        { throw new EmptyQueueException(); }   // ... allora la coda e' vuota
    }
  
    private Stack s;
}