0% found this document useful (0 votes)
16 views46 pages

28 Generics 2

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views46 pages

28 Generics 2

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 46

Generic queues

1
Queue
 example of a queue

2
Front and back of a queue

front back

3
Queue Operations
 classically, queues only support two operations
1. enqueue
 add to the back of the queue
2. dequeue
 remove from the front of the queue
 error to dequeue an empty queue

4
Queue Optional Operations
 optional operations
1. size
 number of elements in the queue
2. isEmpty
 is the queue empty?
3. peek
 get the front element (without removing it)
4. contains
 find the position of a specified element in the queue

5
Enqueue
1. q.enqueue("A")
2. q.enqueue("B")
3. q.enqueue("C")
4. q.enqueue("D")
5. q.enqueue("E")

A B C D E

F B B B B

B
6
Dequeue
1. String s = q.dequeue()

A B C D E

F B

7
Dequeue
1. String s = q.dequeue()
2. s = q.dequeue()

B C D E

F B

8
Dequeue
1. String s = q.dequeue()
2. s = q.dequeue()
3. s = q.dequeue()

C D E

F B

9
Dequeue
1. String s = q.dequeue()
2. s = q.dequeue()
3. s = q.dequeue()
4. s = q.dequeue()

D E

F B

10
Dequeue
1. String s = q.dequeue()
2. s = q.dequeue()
3. s = q.dequeue()
4. s = q.dequeue()
5. s = q.dequeue()

B
11
FIFO
 queue is a First-In-First-Out (FIFO) data structure
 the first element enqueued in the queue is the first element
that can be accessed from the queue

12
Applications
 queues are used widely in computer science and
computer engineering
 online customer queues
 web servers use queues to service requests
 operating systems use queues to distribute resources
 printer, disk, CPU queues
 network devices use queues to determine which packets to
service
 breadth-first search
 https://en.wikipedia.org/wiki/Queueing_theory

13
Queue interface
public interface Queue<E> {
public int size();

default boolean isEmpty() {


return this.size() == 0;
}

public void enqueue(E elem);

public E dequeue();

public E front(); // returns front element

public E back(); // returns back element


}
14
Implementation with List
 a queue implementation using a list is similar to that
for a stack except that dequeue removes the element
at the front of the list

15
import java.util.List;
import java.util.ArrayList;

public class ListQueue<E> implements Queue<E> {


private List<E> q;

public ListQueue() {
this.q = new ArrayList<>();
}

@Override
public int size() {
return this.q.size();
}

@Override
public void enqueue(E elem) {
this.q.add(elem);
}
16
private void throwIfEmpty() {
if (this.isEmpty()) {
throw new RuntimeException("empty queue");
}
}

@Override
public E dequeue() {
this.throwIfEmpty();
return this.q.remove(0);
}

Remove from front of an array-


Remove from front of an array-
based list is in
based list is in

17
@Override
public E front() {
this.throwIfEmpty();
return this.q.get(0);
}

@Override
public E back() {
this.throwIfEmpty();
return this.q.get(this.q.size() - 1);
}

@Override
public String toString() {
return this.q.toString();
}
}

18
Implementation with an array
 the fact that removal and additions occur at different
ends of the queue make an array-based
implementation somewhat tricky
 we use 4 fields:
Field name Purpose
arr array for the elements of the queue
size number of elements in the queue
front array index of element currently at the front of the queue
back array index of element currently at the back of the queue

19
New empty queue

20
enqueue algorithm
 enqueueing an element is similar to pushing an
element onto the top of a stack

1. if arr[length] == size, then make a new array


with greater capacity and copy the existing elements
into the new array
2. move back one position to the right
3. set the element at arr[back] to the enqueued
element

21
After one enqueue

22
After another enqueue

23
After another enqueue

24
After five enqueue operations

25
dequeue algorithm
1. elem = arr[front]
2. arr[front] = null
3. front moves one position to the right
4. return elem

26
After one dequeue

27
After two dequeue operations

28
After four dequeue operations

29
After five dequeue operations

back is one less than front in this empty queue, but this
is not a reliable indicator of an empty queue

30
After one enqueue operation

31
After ten more enqueue operations

32
After one more enqueue operation

back wraps around to the front of the array


back can be less than front in a non-empty queue

33
Example of a full queue

back is one less than front in this full queue (same as in


the previous empty queue example)

34
After eleven more dequeue operations

35
After one more dequeue operation

front wraps around to the front of the array

36
Queue as a circular array
front moves
clockwise during
dequeue

back moves
clockwise during
enqueue

37
public class ArrayQueue<E> implements Queue<E> {

// the default capacity of the queue


private static final int DEFAULT_CAPACITY = 16;

// the array that stores the queue


private Object[] arr;

// the index of the element at the front of the queue


private int front;

// the index of the element at the back of the queue


private int back;

// the number of elements in the queue


private int size;

38
public ArrayQueue() {
this.arr = new Object[ArrayQueue.DEFAULT_CAPACITY];
this.front = 0;
this.back = -1;
this.size = 0;
}

public ArrayQueue(ArrayQueue<E> other) {


this.arr = Arrays.copyOf(other.arr, other.arr.length);
this.front = other.front;
this.back = other.back;
this.size = other.size;
}

39
@Override
public E front() {
if (this.isEmpty()) {
throw new RuntimeException("no front element");
}
return (E) this.arr[this.front];
}

@Override
public E back() {
if (this.isEmpty()) {
throw new RuntimeException("no back element");
}
return (E) this.arr[this.back];
}

40
@Override
public E dequeue() {
if (this.isEmpty()) {
throw new RuntimeException("dequeued an empty queue");
}
Object elem = this.arr[this.front];

// null out the value stored in the array


this.arr[this.front] = null;
this.front = (this.front + 1) % this.arr.length;
this.size--;
return (E) elem;
}

41
Resizing the array
 resizing the internal array when it reaches its capacity
is slightly more complicated than for a stack because
the order of the elements is not necessarily from the
beginning of the array to the end

42
Naïve array resizing
 resizing the internal array when it reaches its capacity
is slightly more complicated than for a stack

oops, elements are


out of order
starting from here

43
Correct array resizing
 one way to correctly copy the elements from the old
array is to put the front element of the queue at index
0 of the new array

44
@Override
public void enqueue(E elem) {
if (this.size == this.arr.length) {
Object[] tmp = new Object[this.arr.length * 2];
for (int i = 0; i < this.size; i++) {
tmp[i] = this.arr[(this.front + i) %
this.arr.length];
}
this.arr = tmp;
this.front = 0;
this.back = this.size - 1;
}
this.back = (this.back + 1) % this.arr.length;
this.arr[this.back] = elem;
this.size++;
}

45
Exercises for the student
 implement the following copy constructor without
using a temporary collection

public ArrayQueue(Queue<E> other)

 implement equals where a Queue<E> instance can be


equal to an ArrayQueue<E> instance

46

You might also like