-2

We are trying to compile our program, but we keep getting a NoSuchElementException. Anyone that has a clue on why this keeps occurring? Thanks in advance. In the following I will attach both the code where we implement the exception and also the main method.

EDIT - whole code in the following:

import java.util.Iterator;
import edu.princeton.cs.algs4.*;

public class RandomQueue<Item> implements Iterable<Item> {
    private Item[] queue;
    private int N;
    private int size;

    // Your code goes here.
    public RandomQueue() { // create an empty random queue
        N = 0;
        size = 2;
        queue = (Item[]) new Object[size];
    }

    public boolean isEmpty() {// is it empty?
        if(N == 0) {
            return true;
        } else {
            return false;
        }
    }

    public int size() {// return the number of elements
        return size;
    }

    public void resizeArray() {
        if(3/4*size < N) {
            size = size*2;
            Item[] queueUpdated = (Item[]) new Object[size];
            for(int i = 0; i < queue.length; ++i) {
                queueUpdated[i] = queue[i];
            }
            queue = queueUpdated;
        } else if (N < 1/4*size) {
            size = size/2;
            Item[] queueUpdated = (Item[]) new Object[size];
            for(int i = 0; i < size-1; ++i) {
                queueUpdated[i] = queue[i];                 
            }
            queue = queueUpdated;
        }

    }


    public void enqueue(Item item) {// add an item
        if(N < queue.length) {
            queue[N++] = item;
            resizeArray();
        }
    }

    public Item sample(){ // return (but do not remove) a random item
        if(isEmpty()) {
            throw new RuntimeException("No such elements");
        } else {
            return queue[StdRandom.uniform(N)];
        }
    }

    public Item dequeue(){ // remove and return a random item
        if(isEmpty()) {
            throw new RuntimeException("Queue is empty");
        } else {
            System.out.println(N);
            int indexFraArray = StdRandom.uniform(N);
            Item i = queue[indexFraArray];
            queue[N] = null;
            queue[indexFraArray] = queue[N--];
            resizeArray();
            return i;
        }
    }

    private class RandomQueueIterator<E> implements Iterator<E> {
        int i = 0;
        public boolean hasNext() {
            return i < N;
        }
        public E next() {
            if (!hasNext()) {
                throw new java.util.NoSuchElementException(); // line 88
            }
            i++;
            return (E) dequeue();
        }
        public void remove() {
            throw new java.lang.UnsupportedOperationException();
        }
    }

    public Iterator<Item> iterator() { // return an iterator over the items in 
        random order
        return new RandomQueueIterator();
    }


    // The main method below tests your implementation. Do not change it.
    public static void main(String args[]) {
        // Build a queue containing the Integers 1,2,...,6:
        RandomQueue<Integer> Q = new RandomQueue<Integer>();
        for (int i = 1; i < 7; ++i) Q.enqueue(i); // autoboxing! cool!

        // Print 30 die rolls to standard output
        StdOut.print("Some die rolls: ");
        for (int i = 1; i < 30; ++i) StdOut.print(Q.sample() +" ");
        StdOut.println();

        // Let's be more serious: do they really behave like die rolls?
        int[] rolls= new int [10000];
        for (int i = 0; i < 10000; ++i)
            rolls[i] = Q.sample(); // autounboxing! Also cool!
        StdOut.printf("Mean (should be around 3.5): %5.4f\n", StdStats.mean(rolls));
        StdOut.printf("Standard deviation (should be around 1.7): %5.4f\n",
                StdStats.stddev(rolls));

        // Now remove 3 random values
        StdOut.printf("Removing %d %d %d\n", Q.dequeue(), Q.dequeue(), Q.dequeue());
        // Add 7,8,9
        for (int i = 7; i < 10; ++i) Q.enqueue(i);
        // Empty the queue in random order
        while (!Q.isEmpty()) StdOut.print(Q.dequeue() +" ");
        StdOut.println();

        // Let's look at the iterator. First, we make a queue of colours:
        RandomQueue<String> C= new RandomQueue<String>();
        C.enqueue("red"); C.enqueue("blue"); C.enqueue("green"); 
        C.enqueue("yellow");

        Iterator<String> I = C.iterator();
        Iterator<String> J = C.iterator();

        StdOut.print("Two colours from first shuffle: "+I.next()+" "+I.next()+" ");

        StdOut.print("\nEntire second shuffle: ");
        while (J.hasNext()) StdOut.print(J.next()+" ");

        StdOut.println("\nRemaining two colours from first shuffle: "+I.next()+" "+I.next()); // line 142
    }
}

I compile in cmd and this is the error I get

the error happens here: enter image description here

and here: enter image description here

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
OcA.ND
  • 1
  • 2

1 Answers1

1

Your iterator is modifying your collection. This is non-standard at least and seems to confuse yourself.

You are creating two iterators over your queue C, which has 4 elements in it at this time:

    Iterator<String> I = C.iterator();
    Iterator<String> J = C.iterator();

You ask the former iterator for two elements:

    StdOut.print("Two colours from first shuffle: "+I.next()+" "+I.next()+" ");

This removes (dequeues) those two elements through this line:

        return (E) dequeue();

Now your queue has 2 elements in it. N is 2.

Your try to remove the remaining 2 elements here:

    StdOut.print("\nEntire second shuffle: ");
    while (J.hasNext()) StdOut.print(J.next()+" ");

However, after one element has been removed, J.i is 1 and N is 1, so the iterator J considers the queue exhausted and only gives you this one element. There’s one left. N is 1. Yet you try to remove another two elements:

    StdOut.println("\nRemaining two colours from first shuffle: "+I.next()+" "+I.next()); // line 142

This is bound to fail. Fortunately it does. next calls hasNext, which in turn compares:

        return i < N;

I.i is 2 (since we had previously taken 2 elements from I) and N is 1, so hasNext returns false, which causes next to throw the exception.

The solution is simple and maybe not so simple: Your iterator should not remove any elements from your queue, only return the elements in order.

And the real answer: You should learn to use a debugger. It will be a good investment for you.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thank you for your help. By the way, I forgot to mention that I am not allowed to change the main method. Although, based on your answer, am I supposed to change the part in the private inner class so that it return the elements in order? Would it consist of removing the dequeue part? – OcA.ND Feb 13 '18 at 22:11
  • Yes, you need to remove the `dequeue` call, but you will also need to substitute something else so the method can return something. You may take advantage of the fact that in the inner class you can use the `queue` array in the outer class. – Ole V.V. Feb 13 '18 at 22:17