题注
同样是一片我新浪博客的文章,搬到CSDN中帮助更多的人吧!
题目
Programming Assignment 2: Randomized Queues and Deques
Write a generic data type for a deque and a randomized queue.The goal of this assignment is to implement elementary datastructures using arrays and linked lists, and to introduce you togenerics and iterators.
Dequeue. A double-ended queue or deque(pronounced "deck") is a generalization of a stack and a queue thatsupports inserting and removing items from either the front or theback of the data structure. Create a generic data typeDeque that implements the following API:
public class Deque implements Iterable {public Deque() // construct an empty deque public boolean isEmpty() // is the deque empty? public int size() // return the number of items on the deque public void addFirst(Item item) // insert the item at the front public void addLast(Item item) // insert the item at the end public Item removeFirst() // delete and return the item at the front public Item removeLast() // delete and return the item at the end public Iterator iterator() // return an iterator over items in order from front to end }
Throw a java.lang.NullPointerException if the clientattempts to add a null item; throw ajava.util.NoSuchElementException if the client attempts toremove an item from an empty deque; throw ajava.lang.UnsupportedOperationExce
Your deque implementation should support each deque operation inconstant worst-case time and use space proportional to thenumber of itemscurrently in the deque. Additionally, youriterator implementation should support the operationsnext() andhasNext() (plus construction) inconstant worst-case time and use a constant amount of extra spaceper iterator.
Randomized queue. A randomized queue is similarto a stack or queue, except that the item removed is chosenuniformly at random from items in the data structure. Create ageneric data typeRandomizedQueue that implements thefollowing API:
public class RandomizedQueue implements Iterable {public RandomizedQueue() // construct an empty randomized queue public boolean isEmpty() // is the queue empty? public int size() // return the number of items on the queue public void enqueue(Item item) // add the item public Item dequeue() // delete and return a random item public Item sample() // return (but do not delete) a random item public Iterator iterator() // return an independent iterator over items in random order }
Throw a java.lang.NullPointerException if the clientattempts to add a null item; throw ajava.util.NoSuchElementException if the client attempts tosample or dequeue an item from an empty randomized queue; throw ajava.lang.UnsupportedOperationExce
Your randomized queue implementation should support eachrandomized queue operation (besides creating an iterator) inconstant amortized time and use space proportional to thenumber of itemscurrently in the queue. That is, anysequence ofM randomized queue operations (starting froman empty queue) should take at mostcM steps in the worstcase, for some constantc. Additionally, your iteratorimplementation should support construction in time linear in thenumber of items and it should support the operationsnext() andhasNext() in constant worst-case time;you may use a linear amount of extra memory per iterator. The orderof two or more iterators to the same randomized queue should bemutually independent; each iterator must maintain its ownrandom order.
Subset client. Write a client programSubset.java that takes a command-line integerk,reads in a sequence ofN strings from standard input usingStdIn.readString(), and prints out exactlyk ofthem, uniformly at random. Each item from the sequence can beprinted out at most once. You may assume thatk ≥ 0 and nogreater than the number of string on standard input.
Your client should use only constant space plus one object eitherof type Deque or of type RandomizedQueue; usegenerics properly to avoid casting and compiler warnings. It shouldalso use time and space proportional to at most N in theworst case, where N is the number of strings on standardinput. (For an extra challenge, use space proportional to k.) It should have the following API.% echo A B C D E F G H I | java Subset 3 C G A % echo AA BB BB BB BB BB CC CC | java Subset 8 BB AA BB CC BB BB CC BB % echo A B C D E F G H I | java Subset 3 E F G
Deliverables. Submit only Deque.java, RandomizedQueue.java, and Subset.java. We willsupply stdlib.jar. You may not call any library functionsother than those in java.lang and stdlib.jar.public class Subset {public static void main(String[] args) }
分析
代码
1. Deque.java
public class Deque<Item> implements Iterable<Item> {
private int N; // number of elements on queue
private Node first; // beginning of queue
private Node last; // end of queue
// helper linked list class
private class Node {
private Item item;
private Node next;
private Node previous;
}
public Deque() {
first = null;
last = null;
N = 0;
}
public boolean isEmpty() {
return N == 0;
}
public int size() {
return N;
}
// insert the item at the front
public void addFirst(Item item){
if (item == null){
throw new java.lang.NullPointerException();
}
Node oldfirst = first;
first = new Node();
first.item = item;
first.previous = null;
if (isEmpty()){
last = first;
first.next = null;
}else{
oldfirst.previous = first;
first.next = oldfirst;
}
N++;
}
// insert the item at the end
public void addLast(Item item){
if (item == null){
throw new java.lang.NullPointerException();
}
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()){
first = last;
last.previous = null;
}else{
oldlast.next = last;
last.previous = oldlast;
}
N++;
}
// delete and return the item at the front
public Item removeFirst(){
if (isEmpty()) throw new java.util.NoSuchElementException();
Item item = first.item;
first = first.next;
N--;
if (isEmpty()){
last = null;
first = null;
}else{
first.previous = null;
}
return item;
}
// delete and return the item at the end
public Item removeLast(){
if (isEmpty()) throw new java.util.NoSuchElementException();
Item item = last.item;
last = last.previous;
N--;
if (isEmpty()){
last = null;
first = null;
}else{
last.next = null;
}
return item;
}
public java.util.Iterator<Item> iterator() {
return new ListIterator();
}
// an iterator, doesn't implement remove() since it's optional
private class ListIterator implements java.util.Iterator<Item> {
private Node current = first;
public boolean hasNext() { return current != null; }
public void remove() { throw new java.lang.UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new java.util.NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
}
2. RandomizedQueue.java
public class RandomizedQueue<Item> implements Iterable<Item> {
private Item[] q; // queue elements
private int N = 0; // number of elements on queue
// cast needed since no generic array creation in Java
public RandomizedQueue() {
q = (Item[]) new Object[2];
}
public boolean isEmpty(){
return N == 0;
}
public int size(){
return N;
}
// resize the underlying array
private void resize(int max) {
assert max >= N;
Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < N; i++) {
temp[i] = q[i];
}
q = temp;
}
public void enqueue(Item item) {
if (item == null){
throw new java.lang.NullPointerException();
}
// double size of array if necessary and recopy to front of array
if (N == q.length) resize(2*q.length); // double size of array if necessary
q[N] = item; // add item
N++;
}
public Item dequeue() {
if (isEmpty()) throw new java.util.NoSuchElementException();
int index = StdRandom.uniform(N);
Item item = q[index];
if (index != N-1){
q[index] = q[N-1];
}
q[N-1] = null; // to avoid loitering
N--;
if (N > 0 && N == q.length/4) resize(q.length/2);
return item;
}
// return (but do not delete) a random item
public Item sample(){
if (isEmpty()) throw new java.util.NoSuchElementException();
int index = (StdRandom.uniform(N));
return q[index];
}
public java.util.Iterator<Item> iterator() { return new ArrayIterator(); }
// an iterator, doesn't implement remove() since it's optional
private class ArrayIterator implements java.util.Iterator<Item> {
private Item[] tempItem = (Item[]) new Object[q.length];
private int tempN = N;
public boolean hasNext() { return tempN != 0; }
public void remove() { throw new UnsupportedOperationException(); }
public ArrayIterator(){
for (int j=0; j<q.length; j++){
tempItem[j] = q[j];
}
}
public Item next() {
if (!hasNext()) throw new java.util.NoSuchElementException();
int index = (StdRandom.uniform(tempN));
Item item = tempItem[index];
if (index != tempN-1){
tempItem[index] = tempItem[tempN-1];
}
tempItem[tempN-1] = null; // to avoid loitering
tempN--;
return item;
}
}
public static void main(String[] args) {
RandomizedQueue<String> q = new RandomizedQueue<String>();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
if (!item.equals("-")) q.enqueue(item);
else if (!q.isEmpty()) StdOut.print(q.dequeue() + " ");
}
StdOut.println("(" + q.size() + " left on queue)");
}
}
3. Subset.java
public class Subset {
public static void main(String[] args){
RandomizedQueue<String> q = new RandomizedQueue<String>();
int k = Integer.valueOf(args[0]);
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
q.enqueue(item);
}
while (k > 0){
StdOut.println(q.dequeue());
k--;
}
}
}