前言 Algorithm-Part-One 第二周主要是讲栈和队列,这基本上是大学时期都讲烂的东西,但还是认真看完了视频。本周的作业当然也是跟队列有关的。主要是实现一个双端队列和一个随机队列,这可以说是所有课程当中最轻松的一个变成作业了。难度不大,但需要认真和细心。
Assignment 具体Assignment可以查看这里:http://coursera.cs.princeton.edu/algs4/assignments/queues.html。
本周任务主要是实现如下API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Deque <Item> implements Iterable <Item> { public Deque () public boolean isEmpty () public int size () public void addFirst (Item item) public void addLast (Item item) public Item removeFirst () public Item removeLast () public Iterator<Item> iterator () public static void main (String[] args) } public class RandomizedQueue <Item> implements Iterable <Item> { public RandomizedQueue () public boolean isEmpty () public int size () public void enqueue (Item item) public Item dequeue () public Item sample () public Iterator<Item> iterator () public static void main (String[] args) }
实现 任务1 对于第一个任务,使用链表数据结构来完成。相对节省内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 package part1_week2;import edu.princeton.cs.algs4.StdOut;import java.util.Iterator;import java.util.NoSuchElementException;public class Deque <Item> implements Iterable <Item> { private Node first; private Node last; private int size; public Deque () { } public boolean isEmpty () { return size == 0 ; } public int size () { return size; } public void addFirst (Item item) { if (item == null ) throw new IllegalArgumentException (); Node node = new Node (); node.value = item; node.next = first; node.prev = null ; if (first != null ) { first.prev = node; } if (last == null ) last = node; first = node; size++; } public void addLast (Item item) { if (item == null ) throw new IllegalArgumentException (); Node node = new Node (); node.value = item; node.next = null ; node.prev = last; if (last != null ) { last.next = node; } if (first == null ) first = node; last = node; size++; } public Item removeFirst () { if (isEmpty()) throw new NoSuchElementException (); Node tempFirst = first; first = first.next; if (first != null ) first.prev = null ; tempFirst.prev = null ; tempFirst.next = null ; size--; return tempFirst.value; } public Item removeLast () { if (isEmpty()) throw new NoSuchElementException (); Node tempLast = last; last = last.prev; if (last != null ) last.next = null ; tempLast.prev = null ; tempLast.next = null ; size--; if (isEmpty()) first = null ; return tempLast.value; } public Iterator<Item> iterator () { return new Itr (first); } private class Node { private Item value; private Node prev; private Node next; } public static void main (String[] args) { Deque<Integer> deque = new Deque <Integer>(); deque.addFirst(0 ); deque.removeLast(); for (Integer i : deque) { StdOut.println(i); } } private class Itr implements Iterator <Item> { Node firstNode; public Itr (Node first) { if (first != null ) { this .firstNode = new Node (); this .firstNode.value = first.value; this .firstNode.prev = first.prev; this .firstNode.next = first.next; } } @Override public boolean hasNext () { return firstNode != null ; } @Override public Item next () { if (!hasNext()) throw new NoSuchElementException (); Item next = firstNode.value; firstNode = firstNode.next; return next; } @Override public void remove () { throw new UnsupportedOperationException (); } } }
任务2 对于第一个任务,参考了Java自带的ArrayList实现方法,使用数组来保存内部元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 package part1_week2;import edu.princeton.cs.algs4.StdOut;import edu.princeton.cs.algs4.StdRandom;import java.util.Arrays;import java.util.Iterator;import java.util.NoSuchElementException;public class RandomizedQueue <Item> implements Iterable <Item> { private static final int INITIAL_CAPACITY = 16 ; private static final int GROW_CAPACITY = 16 ; private Item[] items; private int size; public RandomizedQueue () { items = (Item[]) new Object [INITIAL_CAPACITY]; } public boolean isEmpty () { return size == 0 ; } public int size () { return size; } public void enqueue (Item item) { if (item == null ) throw new IllegalArgumentException (); ensureCapacity(size + 1 ); items[size++] = item; } public Item dequeue () { if (isEmpty()) throw new NoSuchElementException (); int index = StdRandom.uniform(size); Item oldValue = items[index]; int numMoved = size - index - 1 ; if (numMoved > 0 ) System.arraycopy(items, index + 1 , items, index, numMoved); items[--size] = null ; return oldValue; } public Item sample () { if (isEmpty()) throw new NoSuchElementException (); int index = StdRandom.uniform(size); return items[index]; } public Iterator<Item> iterator () { return new Itr (); } private void ensureCapacity (int minCapacity) { if (minCapacity > items.length) { int oldCapacity = items.length; int newCapacity = oldCapacity + GROW_CAPACITY; if (newCapacity - minCapacity < 0 ) newCapacity = minCapacity; items = Arrays.copyOf(items, newCapacity); } } private class Itr implements Iterator <Item> { private Item[] randomItems; int cursor = 0 ; public Itr () { randomItems = Arrays.copyOf(items, size); StdRandom.shuffle(randomItems); } @Override public boolean hasNext () { return cursor < size; } @Override public Item next () { if (!hasNext()) throw new NoSuchElementException (); return randomItems[cursor++]; } @Override public void remove () { throw new UnsupportedOperationException (); } } public static void main (String[] args) { RandomizedQueue<Integer> queue = new RandomizedQueue <>(); queue.enqueue(1 ); queue.enqueue(2 ); queue.enqueue(3 ); queue.enqueue(4 ); queue.dequeue(); queue.dequeue(); for (Integer i : queue) { StdOut.println(i); } } }
想要查看全部源码,传送门:Princeton-Algorithm
总结 尽管题目简单,但是想要写好一个高效可用的Queue,需要考虑内部数据结构如何存储、边界条件,甚至要考虑多线程的情况。优化了很久,最终还是只得了97分,略微遗憾。我知道忙不是借口,但是的确分身乏术,公司的事情还是得优先考虑,后面有时间一定会继续优化!