Advanced Object-oriented Programming Lecture 7akridel/COMP213-Fall2016...Advanced Object-oriented...

Post on 04-Jun-2020

3 views 0 download

Transcript of Advanced Object-oriented Programming Lecture 7akridel/COMP213-Fall2016...Advanced Object-oriented...

COMP 213Advanced Object-oriented Programming

Lecture 7

The Queue ADT.

Stacks vs. Queues

• The queue is the logical counterpart of the stack.

• Stack is a LIFO structure vs. Queue is a FIFO structure.

• Whichever element is in the queue the longest is the next element to be removed.

Stacks vs. Queues

• The queue is the logical counterpart of the stack.

• Stack is a LIFO structure vs. Queue is a FIFO structure.

• Whichever element is in the queue the longest is the next element to be removed.

Stacks vs. Queues

• The queue is the logical counterpart of the stack.

• Stack is a LIFO structure vs. Queue is a FIFO structure.

• Whichever element is in the queue the longest is the next element to be removed.

The (FIFO) Queue

• A data structure in which elements enter at one end and are removed from the opposite end is called a queue.

• Cars passing through the stages of a car wash.

• A line of students waiting to pay for their textbooks at a university bookstore.

• To add elements to a queue, we access the rear of the queue; to remove elements, we access the front. The middle elements are logically inaccessible.

The (FIFO) Queue

• A data structure in which elements enter at one end and are removed from the opposite end is called a queue.

• Cars passing through the stages of a car wash.

• A line of students waiting to pay for their textbooks at a university bookstore.

• To add elements to a queue, we access the rear of the queue; to remove elements, we access the front. The middle elements are logically inaccessible.

The (FIFO) Queue

• A data structure in which elements enter at one end and are removed from the opposite end is called a queue.

• Cars passing through the stages of a car wash.

• A line of students waiting to pay for their textbooks at a university bookstore.

• To add elements to a queue, we access the rear of the queue; to remove elements, we access the front. The middle elements are logically inaccessible.

The (FIFO) Queue

• A data structure in which elements enter at one end and are removed from the opposite end is called a queue.

• Cars passing through the stages of a car wash.

• A line of students waiting to pay for their textbooks at a university bookstore.

• To add elements to a queue, we access the rear of the queue; to remove elements, we access the front. The middle elements are logically inaccessible.

Operations on Queues

• We usually do not directly manipulate the values of elements that are currently in the queue.

• 2 main operations:

• New elements can be added to the rear of the queue, an operation that we call enqueue.

• We can remove elements from the front of the queue, an operation that we call dequeue.

Operations on Queues

• We usually do not directly manipulate the values of elements that are currently in the queue.

• 2 main operations:

• New elements can be added to the rear of the queue, an operation that we call enqueue.

• We can remove elements from the front of the queue, an operation that we call dequeue.

If we want to change the value of an element, we should take that element from the front of the queue, change its value, and return it to the back of the queue.

Operations on Queues

• We usually do not directly manipulate the values of elements that are currently in the queue.

• 2 main operations:

• New elements can be added to the rear of the queue, an operation that we call enqueue.

• We can remove elements from the front of the queue, an operation that we call dequeue.

If we want to change the value of an element, we should take that element from the front of the queue, change its value, and return it to the back of the queue.

Operations on Queues

• We usually do not directly manipulate the values of elements that are currently in the queue.

• 2 main operations:

• New elements can be added to the rear of the queue, an operation that we call enqueue.

• We can remove elements from the front of the queue, an operation that we call dequeue.

If we want to change the value of an element, we should take that element from the front of the queue, change its value, and return it to the back of the queue.

Not standard names; you can get “enq”, “add”, “insert” and “deq”, “remove”, “serve”.

Using Queues

• Often used for system programming purposes:

• An operating system often maintains a queue of processes that are ready to execute or that are waiting for a particular event to occur.

• Computer systems must often provide a “holding area” for messages that are being transmitted between two processes, programs, or even systems. This is usually called a “buffer” and is often implemented as a queue.

• Many other applications need to store requests before processing, e.g., providing a service to customers.

• Other applications that simulate and analyse real-world queues.

Using Queues

• Often used for system programming purposes:

• An operating system often maintains a queue of processes that are ready to execute or that are waiting for a particular event to occur.

• Computer systems must often provide a “holding area” for messages that are being transmitted between two processes, programs, or even systems. This is usually called a “buffer” and is often implemented as a queue.

• Many other applications need to store requests before processing, e.g., providing a service to customers.

• Other applications that simulate and analyse real-world queues.

Using Queues

• Often used for system programming purposes:

• An operating system often maintains a queue of processes that are ready to execute or that are waiting for a particular event to occur.

• Computer systems must often provide a “holding area” for messages that are being transmitted between two processes, programs, or even systems. This is usually called a “buffer” and is often implemented as a queue.

• Many other applications need to store requests before processing, e.g., providing a service to customers.

• Other applications that simulate and analyse real-world queues.

Formal Specification

• Our queues are generic – the type of object held by a particular queue is indicated by the client.

• We provide observer operations isEmpty and isFull.

• We create a QueueInterface that defines the signatures of the queue methods that do not depend on the boundedness of the queue.

• We create a BoundedQueueInterface and an UnboundedQueueInterface, which extend QueueInterface and define the remaining pertinent method signatures; an implementation of a queue should implement one of these two interfaces.

Formal Specification

• Our queues are generic – the type of object held by a particular queue is indicated by the client.

• We provide observer operations isEmpty and isFull.

• We create a QueueInterface that defines the signatures of the queue methods that do not depend on the boundedness of the queue.

• We create a BoundedQueueInterface and an UnboundedQueueInterface, which extend QueueInterface and define the remaining pertinent method signatures; an implementation of a queue should implement one of these two interfaces.

Formal Specification

• Our queues are generic – the type of object held by a particular queue is indicated by the client.

• We provide observer operations isEmpty and isFull.

• We create a QueueInterface that defines the signatures of the queue methods that do not depend on the boundedness of the queue.

• We create a BoundedQueueInterface and an UnboundedQueueInterface, which extend QueueInterface and define the remaining pertinent method signatures; an implementation of a queue should implement one of these two interfaces.

Formal Specification

• Our queues are generic – the type of object held by a particular queue is indicated by the client.

• We provide observer operations isEmpty and isFull.

• We create a QueueInterface that defines the signatures of the queue methods that do not depend on the boundedness of the queue.

• We create a BoundedQueueInterface and an UnboundedQueueInterface, which extend QueueInterface and define the remaining pertinent method signatures; an implementation of a queue should implement one of these two interfaces.

QueueInterface

// Interface for a class that implements a queue of Objects// A queue is a “first in, first out” structure.public interface QueueInterface {

// Checks if this queue is empty; otherwise removes front element and returns it.Object dequeue();

// Returns true if this queue is empty; otherwise, returns false.boolean isEmpty();

}

QueueInterface

// Interface for a class that implements a queue of Objects// A queue is a “first in, first out” structure.public interface QueueInterface {

// Checks if this queue is empty; otherwise removes front element and returns it.Object dequeue();

// Returns true if this queue is empty; otherwise, returns false.boolean isEmpty();

}

QueueInterface

// Interface for a class that implements a queue of Objects// A queue is a “first in, first out” structure.public interface QueueInterface {

// Checks if this queue is empty; otherwise removes front element and returns it.Object dequeue();

// Returns true if this queue is empty; otherwise, returns false.boolean isEmpty();

}

QueueInterface

// Interface for a class that implements a queue of Objects// A queue is a “first in, first out” structure.public interface QueueInterface {

// Checks if this queue is empty; otherwise removes front element and returns it.Object dequeue();

// Returns true if this queue is empty; otherwise, returns false.boolean isEmpty();

}

QueueInterface

// Interface for a class that implements a queue of Objects// A queue is a “first in, first out” structure.public interface QueueInterface {

// Checks if this queue is empty; otherwise removes front element and returns it.Object dequeue();

// Returns true if this queue is empty; otherwise, returns false.boolean isEmpty();

}

Unbounded vs. bounded queues

Main difference is the need for the latter to handle the potential of overflow. In the bounded queue interface, we define the signature for an isFull method.

BoundedQueueInterface

// Interface for a class that implements a queue of Objects with a bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface BoundedQueueInterface extends QueueInterface {

// Checks if this queue is full; if not, it adds element// to the rear of this queue.void enqueue(Object element);

// Returns true if this queue is full; otherwise, returns false.boolean isFull();

}

BoundedQueueInterface

// Interface for a class that implements a queue of Objects with a bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface BoundedQueueInterface extends QueueInterface {

// Checks if this queue is full; if not, it adds element// to the rear of this queue.void enqueue(Object element);

// Returns true if this queue is full; otherwise, returns false.boolean isFull();

}

BoundedQueueInterface

// Interface for a class that implements a queue of Objects with a bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface BoundedQueueInterface extends QueueInterface {

// Checks if this queue is full; if not, it adds element// to the rear of this queue.void enqueue(Object element);

// Returns true if this queue is full; otherwise, returns false.boolean isFull();

}

BoundedQueueInterface

// Interface for a class that implements a queue of Objects with a bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface BoundedQueueInterface extends QueueInterface {

// Checks if this queue is full; if not, it adds element// to the rear of this queue.void enqueue(Object element);

// Returns true if this queue is full; otherwise, returns false.boolean isFull();

}

BoundedQueueInterface

// Interface for a class that implements a queue of Objects with a bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface BoundedQueueInterface extends QueueInterface {

// Checks if this queue is full; if not, it adds element// to the rear of this queue.void enqueue(Object element);

// Returns true if this queue is full; otherwise, returns false.boolean isFull();

}

UnboundedQueueInterface

// Interface for a class that implements a queue of Objects with no bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface UnboundedQueueInterface extends QueueInterface {

// Adds element to the rear of the queuevoid enqueue(Object element);

}

UnboundedQueueInterface

// Interface for a class that implements a queue of Objects with no bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface UnboundedQueueInterface extends QueueInterface {

// Adds element to the rear of the queuevoid enqueue(Object element);

}

UnboundedQueueInterface

// Interface for a class that implements a queue of Objects with no bound// on the size of the queue. A queue is a “first in, first out” structure.

public interface UnboundedQueueInterface extends QueueInterface {

// Adds element to the rear of the queuevoid enqueue(Object element);

}

Diagram of our Queue interfaces

<<interface>>QueueInterface

+dequeue(): Object+isEmpty(): boolean

<<interface>>UnboundedQueueInterface

+enqueue(Object element): void

<<interface>>BoundedQueueInterface

+enqueue(Object element): void

+isFull(): boolean

Diagram of our Queue interfaces

<<interface>>QueueInterface

+dequeue(): Object+isEmpty(): boolean

<<interface>>UnboundedQueueInterface

+enqueue(Object element): void

<<interface>>BoundedQueueInterface

+enqueue(Object element): void

+isFull(): boolean

By virtue of the interface inheritance rules, the implementation must also implement the methods of QueueInterface.

Array-Based Implementation for bounded queue

• Class ArrayBoundedQueue that implements the BoundedQueueInterface.

• Several possible alternatives for storing the queue in an array:

• Fixed-Front Design

• Floating-Front Design

Array-Based Implementation for bounded queue

• Class ArrayBoundedQueue that implements the BoundedQueueInterface.

• Several possible alternatives for storing the queue in an array:

• Fixed-Front Design

• Floating-Front Design

Array-Based Implementation for bounded queue

• Class ArrayBoundedQueue that implements the BoundedQueueInterface.

• Several possible alternatives for storing the queue in an array:

• Fixed-Front Design

• Floating-Front Design

Fixed-Front design

• We keep the front of the queue fixed in the first array slot & let the rear move as we add new elements

A B C D

[0] [1] [2] [3] [4]

Fixed-Front design

• We keep the front of the queue fixed in the first array slot & let the rear move as we add new elements

B C D

[0] [1] [2] [3] [4]

Fixed-Front design

• We keep the front of the queue fixed in the first array slot & let the rear move as we add new elements

B C D

[0] [1] [2] [3] [4]

Fixed-Front design

• We keep the front of the queue fixed in the first array slot & let the rear move as we add new elements

B C D

[0] [1] [2] [3] [4]With this design the enqueueoperation is the same as pushin Stacks. The dequeueoperationis more complicated than pop.

Evaluation of design

• Strengths:

• simplicity

• easy coding

• Weakness:

• having to move all elements up every time we dequeue

Evaluation of design

• Strengths:

• simplicity

• easy coding

• Weakness:

• having to move all elements up every time we dequeue

How serious is this?To answer, we need to know

something about the intended use of the queue (generally, not the most

efficient choice, though!).

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

A

[0] [1] [2] [3] [4]

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

A B

[0] [1] [2] [3] [4]

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

A B C

[0] [1] [2] [3] [4]

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

B C

[0] [1] [2] [3] [4]

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

B C D

[0] [1] [2] [3] [4]

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

L M

[0] [1] [2] [3] [4]

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

L M

[0] [1] [2] [3] [4]

No room at end of arrayfront: 3rear: 5?

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

L M

[0] [1] [2] [3] [4]

• A solution is to let the queue elements “wrap around” the end of the array (treat the array as a circular structure).

Floating-Front design

• We allow both the front and the rear to move.

• Letting the queue elements float in the array creates a new problem when the rear indicator gets to the end of the array.

N L M

[0] [1] [2] [3] [4]

• A solution is to let the queue elements “wrap around” the end of the array (treat the array as a circular structure).

Floating-Front design

• To get the next position for the rear indicator, we can use an if statement. Assume that capacity represents the size of the array:

if(rear == (capacity - 1))rear = 0;

elserear = rear+1;

• Another way to reset rear is by using the modulo (%) operator:

rear = (rear+1) % capacity;

Comparing design approaches

• The floating-front is not as simple as the fixed-front.

• By using a more efficient dequeue operation, we gain in performance.

• We will use the floating-front approach.

Comparing design approaches

• The floating-front is not as simple as the fixed-front.

• By using a more efficient dequeue operation, we gain in performance.

• We will use the floating-front approach.

The Instance Variables and Constructors

• What instance variables does our implementation need?

• We need the queue elements themselves (held in the underlying array).

• We must add two instance variables to the class: front and rear.

• We know that to help wrap around the value of rear, we need to know the array’s capacity.

• For the isEmpty and isFull operations, we need the numElements.

The Instance Variables and Constructors

• What instance variables does our implementation need?

• We need the queue elements themselves (held in the underlying array).

• We must add two instance variables to the class: front and rear.

• We know that to help wrap around the value of rear, we need to know the array’s capacity.

• For the isEmpty and isFull operations, we need the numElements.

The Instance Variables and Constructors

• What instance variables does our implementation need?

• We need the queue elements themselves (held in the underlying array).

• We must add two instance variables to the class: front and rear.

• We know that to help wrap around the value of rear, we need to know the array’s capacity.

• For the isEmpty and isFull operations, we need the numElements.

The Instance Variables and Constructors

• What instance variables does our implementation need?

• We need the queue elements themselves (held in the underlying array).

• We must add two instance variables to the class: front and rear.

• We know that to help wrap around the value of rear, we need to know the array’s capacity.

• For the isEmpty and isFull operations, we need the numElements.

We can now handle the enqueue& dequeue operations

The Instance Variables and Constructors

• What instance variables does our implementation need?

• We need the queue elements themselves (held in the underlying array).

• We must add two instance variables to the class: front and rear.

• We know that to help wrap around the value of rear, we need to know the array’s capacity.

• For the isEmpty and isFull operations, we need the numElements.

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue

// Two constructors are provided: one that creates a queue of default // capacity & one that allows the main method to specify the capacity.public class ArrayBoundedQueue implements BoundedQueueInterface {

protected final int DEFAULTCAP = 100; // default capacityprotected Object[] queue; // array that holds queue elementsprotected int numElements = 0; // number of elements in the queueprotected int front = 0; // index of front of queueprotected int rear; // index of rear of queuepublic ArrayBoundedQueue() {

queue = new Object[DEFAULTCAP];rear = DEFAULTCAP - 1;

}public ArrayBoundedQueue(int maxSize) {

queue = new Object[maxSize];rear = maxSize - 1;

}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic void enqueue(Object element) {

if (isFull())System.out.println("Enqueue was attempted on a full queue!");

else {rear = (rear + 1) % queue.length;queue[rear] = element;numElements = numElements + 1;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic void enqueue(Object element) {

if (isFull())System.out.println("Enqueue was attempted on a full queue!");

else {rear = (rear + 1) % queue.length;queue[rear] = element;numElements = numElements + 1;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic void enqueue(Object element) {

if (isFull())System.out.println("Enqueue was attempted on a full queue!");

else {rear = (rear + 1) % queue.length;queue[rear] = element;numElements = numElements + 1;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic void enqueue(Object element) {

if (isFull())System.out.println("Enqueue was attempted on a full queue!");

else {rear = (rear + 1) % queue.length;queue[rear] = element;numElements = numElements + 1;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic void enqueue(Object element) {

if (isFull())System.out.println("Enqueue was attempted on a full queue!");

else {rear = (rear + 1) % queue.length;queue[rear] = element;numElements = numElements + 1;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic void enqueue(Object element) {

if (isFull())System.out.println("Enqueue was attempted on a full queue!");

else {rear = (rear + 1) % queue.length;queue[rear] = element;numElements = numElements + 1;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic Object dequeue() {

if (isEmpty()) {System.out.println("Dequeue attempted on an empty queue!");return null;

} else {Object itemToReturn = queue[front];queue[front] = null;front = (front + 1) % queue.length;numElements = numElements - 1;return itemToReturn;

}}...

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic boolean isEmpty() {

return (numElements == 0);}

@Overridepublic boolean isFull() {

return (numElements == queue.length);}

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic boolean isEmpty() {

return (numElements == 0);}

@Overridepublic boolean isFull() {

return (numElements == queue.length);}

}

Implementation of our queue (cont.)

public class ArrayBoundedQueue implements BoundedQueueInterface {...@Overridepublic boolean isEmpty() {

return (numElements == 0);}

@Overridepublic boolean isFull() {

return (numElements == queue.length);}

}

Test Plan

• We should make a comprehensive test plan for our (queue) implementations, listing all of the operations & tests needed for each operation.

• E.g., to test the method isEmpty, we should call it at least in the following scenarios:

• The queue is originally empty.

• The queue is nonempty.

• The queue is empty after having been nonempty.

• The queue has cycled through the empty and nonempty states a few times and is now nonempty.

• The queue is full.

Test Plan

• We should make a comprehensive test plan for our (queue) implementations, listing all of the operations & tests needed for each operation.

• E.g., to test the method isEmpty, we should call it at least in the following scenarios:

• The queue is originally empty.

• The queue is nonempty.

• The queue is empty after having been nonempty.

• The queue has cycled through the empty and nonempty states a few times and is now nonempty.

• The queue is full.

Test Plan (cont.)

• We might enqueue elements until the queue is full and then call methods isEmptyand isFull to see whether they correctly judge the state of the queue.

• We could then dequeue the elements in the queue, printing them out as we go to make sure that they are correctly removed.

• We must also remember to test the more intricate part of the array-based algorithm:

• We enqueue until full;

• dequeue an element;

• then enqueue again, forcing the operation to circle back to the beginning of the array.

Test Plan (cont.)

• We might enqueue elements until the queue is full and then call methods isEmptyand isFull to see whether they correctly judge the state of the queue.

• We could then dequeue the elements in the queue, printing them out as we go to make sure that they are correctly removed.

• We must also remember to test the more intricate part of the array-based algorithm:

• We enqueue until full;

• dequeue an element;

• then enqueue again, forcing the operation to circle back to the beginning of the array.

Test Plan (cont.)

• We might enqueue elements until the queue is full and then call methods isEmptyand isFull to see whether they correctly judge the state of the queue.

• We could then dequeue the elements in the queue, printing them out as we go to make sure that they are correctly removed.

• We must also remember to test the more intricate part of the array-based algorithm:

• We enqueue until full;

• dequeue an element;

• then enqueue again, forcing the operation to circle back to the beginning of the array.

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Example Use

import java.util.Scanner;public class Main {

public static void main(String[] args) {Scanner putIn = new Scanner(System.in);ArrayBoundedQueue queue = new ArrayBoundedQueue(3);String line;for(int i = 1;i<=3; i++) {

System.out.println("Enter a line of text: ");line = putIn.nextLine();queue.enqueue(line);

}System.out.println("The queue elements are: ");while(!queue.isEmpty()) {

line = (String) queue.dequeue();System.out.println(line);

}}

}

Array-Based Implementation for unbounded queue

• Class ArrayUnbQueue that implements the UnboundedQueueInterface.

• The trick here is to create a new larger array, when needed, and copy the structure into the new array.

• No need for isFull method.

Array-Based Implementation for unbounded queue

• Class ArrayUnbQueue that implements the UnboundedQueueInterface.

• The trick here is to create a new larger array, when needed, and copy the structure into the new array.

• No need for isFull method.

Array-Based Implementation for unbounded queue

• Class ArrayUnbQueue that implements the UnboundedQueueInterface.

• The trick here is to create a new larger array, when needed, and copy the structure into the new array.

• No need for isFull method.

Unbounded vs. bounded implementation: what changes?

• enqueue method – to increase the capacity of the array if it has run out of space.

• we implement it as a separate method named enlarge.

• Then, the enqueue method can start with:

if (numElements == queue.length)enlarge();

Unbounded vs. bounded implementation: what changes?

• enqueue method – to increase the capacity of the array if it has run out of space.

• we implement it as a separate method named enlarge.

• Then, the enqueue method can start with:

if (numElements == queue.length)enlarge();

Unbounded vs. bounded implementation: what changes?

• enqueue method – to increase the capacity of the array if it has run out of space.

• we implement it as a separate method named enlarge.

• Then, the enqueue method can start with:

if (numElements == queue.length)enlarge();

Options for the enlarge method

• We could set a constant increment value or multiplying factor within the class.

• We could allow the application to specify an increment value or multiplying factor when the queue is instantiated.

• We could use the original capacity as the increment value.

Options for the enlarge method

• We could set a constant increment value or multiplying factor within the class.

• We could allow the application to specify an increment value or multiplying factor when the queue is instantiated.

• We could use the original capacity as the increment value.

Options for the enlarge method

• We could set a constant increment value or multiplying factor within the class.

• We could allow the application to specify an increment value or multiplying factor when the queue is instantiated.

• We could use the original capacity as the increment value.

Brainstorming

• The enlarge operation is costly ⇒ increment by large amount.

• Increment too much ⇒waste of both time & space.

Brainstorming

• The enlarge operation is costly ⇒ increment by large amount.

• Increment too much ⇒waste of both time & space.

Brainstorming

• The enlarge operation is costly ⇒ increment by large amount.

• Increment too much ⇒waste of both time & space.

Summary

• The Queue ADT

• Our Queue Interfaces

• Our ArrayBoundedQueue implementation

• Next: implementation of unbounded Queues.