本次作业考察利用array 或者linked list 实现规定时间复杂度的queue 和stack, 不能使用java 自带的stack 和queue. 目的是让我们掌握自己设计的函数的复杂度。
Deque成功的关键是
1. 选择合适的数据结构,本题选择doubly LinkedList.
2. 自己写测试代码,测试各种情况。addLast, removeFirst 等等,尤其注意边界情况。
Java code:
//Deque - should be implemented using a doubly linked list import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; import edu.princeton.cs.algs4.StdRandom; import java.util.Iterator; import java.util.NoSuchElementException; /*The goal of this assignment is to implement data types from first principles, *using resizing arrays and linked lists. */ /* * A double-ended queue or deque (pronounced "deck") is a generalization of a stack and a queue that * supports adding and removing items from either the front or the back of the data structure. * * Performance requirements. * Your deque implementation must support each deque operation in constant worst-case time. * A deque containing N items must use at most 48N + 192 bytes of memory. * and use space proportional to the number of items currently in the deque. * * Additionally, your iterator implementation must support each operation (including construction) in constant worst-case time. */ public class Deque<Item> implements Iterable<Item> { private int N; // size of the stack private Node first; private Node last; // helper linked list class private class Node { private Item item; private Node prev; private Node next; } // construct an empty deque public Deque() { N = 0; first = null; last = null; } // is the deque empty? public boolean isEmpty() { return N == 0; } // return the number of items on the deque public int size() { return N; } //Throw a java.lang.NullPointerException if the client attempts to add a null item public void addFirst(Item item) { // add the item to the front if(item == null) { throw new NullPointerException("add a null item"); } Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; first.prev = null; if(isEmpty()) { last = first; } else { oldfirst.prev = first; } N++; } //Throw a java.lang.NullPointerException if the client attempts to add a null item public void addLast(Item item) { // add the item to the end if(item == null) { throw new NullPointerException("add a null item"); } Node oldlast = last; last = new Node(); last.item = item; last.next = null; last.prev = oldlast; if(isEmpty()) { first = last; }else { oldlast.next = last; } N++; } //remove and return the item from the front // throw a java.util.NoSuchElementException if the client attempts to remove an item from an empty deque public Item removeFirst() { if (isEmpty()) { throw new NoSuchElementException("Deque underflow"); } Item item = first.item; // save item to return Node oldfirst = first; first = first.next; // delete first node oldfirst = null; if(first == null) { last = null; } else { first.prev = null; } N--; return item; } // remove and return the item from the end // throw a java.util.NoSuchElementException if the client attempts to remove an item from an empty deque public Item removeLast() { if (isEmpty()) { throw new NoSuchElementException("Deque underflow"); } Item item = last.item; //save item to return Node oldlast = last; last = last.prev; oldlast.prev = null; if(last != null) { last.next = null; }else { first = null; } oldlast = null; N--; return item; } // return an iterator over items in order from front to end public Iterator<Item> iterator() { return new ListIterator(); } private class ListIterator implements Iterator<Item> { private Node current = first; public boolean hasNext() { return current != null; } public void remove() { throw new UnsupportedOperationException(); } public Item next() { if (!hasNext()) { throw new NoSuchElementException(); } Item item = current.item; current = current.next; return item; } } public static void main(String[] args) { // unit testing //testSimpleAddRemove(); testAddRemoveallItems(); } private static void testSimpleAddRemove() { Deque<Integer> d = new Deque<Integer>(); d.addFirst(10); d.addFirst(20); d.addFirst(30); d.addLast(100); d.addLast(101); d.addLast(102); assert d.size() == 6; System.out.println(d.size()); Iterator i = d.iterator(); while (i.hasNext()) { System.out.print(i.next() + " "); } System.out.println(""); System.out.println("d.removeFirst() is " + d.removeFirst()); System.out.println("d.removeLast() is " + d.removeLast()); System.out.println(d.size()); i = d.iterator(); while (i.hasNext()) { System.out.print(i.next() + " "); } System.out.println(""); } private static void testAddRemoveallItems() { Deque<Integer> d = new Deque<Integer>(); d.addFirst(10); //d.addLast(20); Iterator i = d.iterator(); while (i.hasNext()) { System.out.print(i.next() + " "); } System.out.println(""); System.out.println("d.size is " + d.size()); //System.out.println("d.removeFirst() is " + d.removeFirst()); System.out.println("d.removeLast() is " + d.removeLast()); System.out.println("d.size is " + d.size()); } }