Formalizing the Dynamic Semantics of Java

Download Report

Transcript Formalizing the Dynamic Semantics of Java

7
Queue ADTs
• Queue concepts.
• Queue applications.
• A queue ADT: requirements, contract.
• Implementations of queues: using arrays, linked lists.
• Queues in the Java class library.
© 2001, D.A. Watt and D.F. Brown
7-1
Queue concepts
• A queue is a first-in-first-out sequence of elements.
Elements can added only at one end (the rear of the queue)
and removed only at the other end (the front of the queue).
• The length of a queue is the number of elements it
contains.
• An empty queue has length zero.
7-2
Queue concepts (continued)
• Illustration (queue of persons):
BUS
STOP
7-3
Queue applications
• Print server
 maintains a queue of print jobs.
• Disk driver
 maintains a queue of disk input/output requests.
• Scheduler (e.g., in an operating system)
 maintains a queue of processes awaiting a slice of machine time.
7-4
Example 1: demerging (1)
• Consider a file of person records, each of which contains a
person’s name, gender, date of birth, etc. The records are
sorted by date of birth. We are required to rearrange the
records such that females precede males but they remain
sorted by date of birth within each gender group.
• Bad idea: use a sorting algorithm.
Time complexity is O(n log n) at best.
• Good idea: use a demerging algorithm.
Time complexity is O(n).
7-5
Example 1 (2)
• Demerging algorithm:
To rearrange a file of person records such that females precede males
but their order is otherwise unchanged:
1. Make queues females and males empty.
2. Until the input file is empty, repeat:
2.1. Let p be the next person read in from the file.
2.2. If p is female, add p to the rear of females.
2.3. If p is male, add p to the rear of males.
3. Until females is empty, repeat:
3.1. Write out the person removed from the front of females.
4. Until males is empty, repeat:
4.1. Write out the person removed from the front of males.
5. Terminate.
7-6
Queue ADT: requirements
•
Requirements:
1) It must be possible to make a queue empty.
2) It must be possible to test whether a queue is empty.
3) It must be possible to obtain the length of a queue.
4) It must be possible to add an element at the rear of a queue.
5) It must be possible to remove the front element from a queue.
6) It must be possible to access the front element in a queue without
removing it.
7-7
Queue ADT: contract (1)
• Possible contract, expressed as a Java interface:
public interface Queue {
// Each Queue object is a queue whose elements are objects.
/////////////// Accessors ///////////////
public boolean isEmpty ();
// Return true if and only if this queue is empty.
public int size ();
// Return this queue’s length.
public Object getFirst ();
// Return the element at the front of this queue.
7-8
Queue ADT: contract (2)
• Possible contract (continued):
/////////////// Transformers ///////////////
public void clear ();
// Make this queue empty.
public void addLast (Object elem);
// Add elem as the rear element of this queue.
public Object removeFirst ();
// Remove and return the front element of this queue.
}
7-9
Implementation of queues using
arrays (1)
• Consider representing a bounded queue (length  maxlen)
by:
 a variable length, containing the current length
 variables front and rear
 an array elems of length maxlen, containing the queued elements in
elems[front…rear–1]:
unoccupied
0
Invariant:
Empty
queue:
0
front element
rear element
unoccupied
front
element element
rear–1
element
maxlen–1
front=rear
maxlen–1
7-10
Implementation using arrays (2)
• Animation (with maxlen = 6):
After
Initially:
removing
adding
Maggie:
Ralph:
Homer,
the front
Marge,
element:
Bart, Lisa:
0
1
2
elems Homer Marge Bart
front
0
1
2
rear
054
3
4
5
Lisa Maggie Ralph
length
4350
7-11
Implementation using arrays (3)
• If we must shift elements along the array, operations
addLast and removeFirst will have time complexity
O(n).
• We can avoid this if we use a “cyclic array” instead of an
ordinary array.
7-12
Cyclic arrays
• In a cyclic array a of length n, every component has both
a successor and a predecessor. In particular:
 the successor of a[n–1] is a[0]
 the predecessor of a[0] is a[n–1].
• Alternative ways of visualizing
a cyclic array (length 8):
7
0
6
1
5
2
4
0
1
2
3
4
5
3
6
7
7-13
Implementation of queues using cyclic
arrays (1)
• Representing a bounded queue (length  maxlen) by:
 a variable length, containing the current length
 variables front and rear
 a cyclic array elems of length maxlen, containing the queued
elements either in elems[front…rear–1] or in
elems[front…maxlen–1] and elems[0…rear–1].
0
Invariant:
or:
Empty
queue:
0
element
0
front
element element
rear–1
element
maxlen–1
rear–1
element
front
element
maxlen–1
element
front=rear
maxlen–1
7-14
Implementation using cyclic arrays (2)
• Animation (with maxlen = 6):
After
Initially:
adding Martin:
removing
Maggie:
Ralph:
Nelson:
Homer,
the front
Marge,
element:
Bart, Lisa:
0
1
2
elems Nelson
Homer Martin
Marge Bart
front
0
1
2
3
rear
21054
3
4
5
Lisa Maggie Ralph
length
56430
7-15
Implementation using cyclic arrays (3)
• Java implementation:
public class ArrayQueue implements Queue {
private Object[] elems;
private int front, rear, length;
/////////////// Constructor ///////////////
public ArrayQueue (int maxLength) {
elems = new Object[maxLength];
front = rear = length = 0;
}
7-16
Implementation using cyclic arrays (4)
• Java implementation (continued):
/////////////// Accessors ///////////////
public boolean isEmpty () {
return (length == 0);
}
public int size () {
return length;
}
public Object getFirst () {
if (length == 0) throw …;
return elems[front];
}
7-17
Implementation using cyclic arrays (5)
• Java implementation (continued):
/////////////// Transformers ///////////////
public void clear () {
for (int i = 0; i < elems.length; i++)
elems[i] = null;
front = rear = length = 0;
}
public void addLast (Object elem) {
if (length == elems.length) throw …;
elems[rear++] = elem;
if (rear == elems.length) rear = 0;
length++;
}
7-18
Implementation using cyclic arrays (6)
• Java implementation (continued):
public Object removeFirst () {
if (length == 0) throw …;
Object frontElem = elems[front];
elems[front++] = null;
if (front == elems.length) front = 0;
return frontElem;
}
}
• Analysis:
 Most operations have time complexity O(1).
 Operation clear has time complexity O(maxlen).
7-19
Implementation of queues using SLLs
(1)
• Represent an (unbounded) queue by:
 an SLL, whose first node contains the front element, and whose
header contains links to the first node (front) and last node (rear).
 a variable length (optional).
Invariant:
front
rear
Empty
queue:
front
rear
Illustration:
front
rear
element
Homer
element
Marge
element
Bart
Lisa
7-20
Implementation using SLLs (2)
• Java implementation:
public class LinkedQueue implements Queue {
private SLLNode front, rear;
/////////////// Constructor ///////////////
public LinkedQueue () {
front = rear = null;
}
/////////////// Accessors ///////////////
public boolean isEmpty () {
return (front == null);
}
7-21
Implementation using SLLs (3)
• Java implementation (continued):
public int size () {
int length = 0;
for (SLLNode curr = front;
curr != null; curr = curr.succ)
length++;
return length;
}
public Object getFirst () {
if (front == null) throw …;
return front.element;
}
7-22
Implementation using SLLs (4)
• Java implementation (continued):
/////////////// Transformers ///////////////
public void clear () {
front = rear = null;
}
public void addLast (Object elem) {
SLLNode newest = new SLLNode(elem, null);
if (rear != null) rear.succ = newest;
else front = newest;
rear = newest;
}
7-23
Implementation using SLLs (5)
• Java implementation (continued):
public Object removeFirst () {
if (front == null) throw …;
Object frontElem = front.element;
front = front.succ;
if (front == null) rear = null;
return frontElem;
}
}
• Analysis:
 Most operations have time complexity O(1), but size is O(n).
 However, size too would be O(1) if we used a variable length.
7-24
Queues in the Java class library
• Java provides no Queue interface or class as such.
• However, the java.util.LinkedList class provides
all the above Queue operations.
• Illustration:
import java.util.LinkedList;
LinkedList queue = new LinkedList();
queue.addLast("Homer"); queue.addLast("Marge");
queue.addLast("Bart"); queue.addLast("Lisa");
queue.addLast("Maggie");
System.out.println(busQueue.removeFirst());
7-25
Example 2: demerging revisited (1)
• Recall the demerging algorithm of Example 1.
• Implementation:
public static void reSortPersons (
BufferedReader input,
BufferedWriter output)
throws IOException {
LinkedList femaleQueue = new LinkedList();
LinkedList maleQueue = new LinkedList();
for (;;) {
Person p = readPerson(input);
if (p == null) break; // end of input
if (p.female) femaleQueue.addLast(p);
else maleQueue.addLast(p);
}
7-26
Example 2 (2)
• Implementation (continued):
while (! femaleQueue.isEmpty()) {
Person f = femaleQueue.removeFirst();
writePerson(output, f);
}
while (! maleQueue.isEmpty()) {
Person m = maleQueue.removeFirst();
writePerson(output, m);
}
}
7-27