Deque 与 RandomizedQueue 实现
一个人比较缓慢,大多数在于信息不全面、思维碰撞缺乏,在B站上也没有找到相关群体
故此,留一个群号,希望可以共同进步,相互监督,940774008
Deque.java
双端队列,还算是很简单的链式实现。
发现一个小有趣的地方,如果不 implements Iterable<> 直接写 内部类Iterator也是可以的
可以while next,但是无法使用 foreach 语法糖,虽然你实现了 Iterator,以前一直没注意到
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Deque<Item> implements Iterable<Item> {
private Node first; // 8 8
private Node last; // 8 16
private int size; // 4 20
private class Node { // 16-object + 8-innerClass + 8 + 8 + 8 = 48 N
private Item item; // 8
private Node next; // 8
private Node pre; // 8
}
// construct an empty deque
public Deque() {
}
// is the deque empty?
public boolean isEmpty() {
return first == null && last == null;
}
// return the number of items on the deque
public int size() {
return size;
}
// add the item to the front
public void addFirst(Item item) {
// 0.合法性检查
isValid(item);
// 1.存储旧的
Node oldFirst = first;
first = new Node();
first.item = item;
if (oldFirst != null) {
first.next = oldFirst;
oldFirst.pre = first;
}
else
last = first;
size++;
}
// add the item to the back
public void addLast(Item item) {
// 0.合法性检查
isValid(item);
// 1.存储旧的
Node oldLast = last;
last = new Node();
last.item = item;
if (oldLast == null) {
first = last;
}
else {
last.pre = oldLast;
oldLast.next = last;
}
size++;
}
// remove and return the item from the front
public Item removeFirst() {
removeEmpty();
Item item = first.item;
if (size == 1) {
first = null;
last = null;
}
else {
first = first.next;
first.pre = null;
}
size--;
return item;
}
// remove and return the item from the back
public Item removeLast() {
removeEmpty();
Item item = last.item;
if (size == 1) {
first = null;
last = null;
}
else {
last = last.pre;
last.next = null;
}
size--;
return item;
}
// return an iterator over items in order from front to back
public Iterator<Item> iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator<Item> {
private Node current = first; // first Node 16-object + 8-innerClass + 8 = 32
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;
}
}
private void isValid(Item item) {
if (item == null)
throw new IllegalArgumentException();
}
private void removeEmpty() {
if (isEmpty())
throw new NoSuchElementException();
}
// Target : 48n + 192 bytes || constant worst-case time(add/remove/iterator)
// unit testing (required)
public static void main(String[] args) {
Deque<Integer> idq = new Deque<>();
idq.addFirst(1);
idq.addFirst(2);
idq.addFirst(4);
idq.addFirst(3);
Integer integer = idq.removeFirst();
Integer integer1 = idq.removeLast();
System.out.println(integer + "|" + integer1);
Iterator<Integer> iterator = idq.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
需要注意的点是:特殊情况的处理,比如 增加第一个,删除最后一个,这样的边界情况。
剩下的事情就是按部就班的实现就行了。
RandomizedQueue.java
虽然叫做随机队列,但它不符合 队列的FIFO规则,所以,只是习惯上称为 随机队列。
实现思想上,通过数组来作为核心操作对象,原因是:
随机队列实现必须在固定的摊销时间内支持每个随机队列操作
在最坏的情况下,对于常数c,任何m个随机队列操作的混合序列(从空队列开始)必须最多执行cm步
很显然,如果继续使用链式实现,就不是 c * m,而是 n * m
随机队列显然——不要求顺序的,这一点在实现上就会减少很多 搬移数组 的麻烦,所需要做的只有将deque的Item从target索引处取出,然后与最后size索引处的Item交换,然后将size处置空即可。
import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class RandomizedQueue<Item> implements Iterable<Item> {
private Item[] rq;
private int size;
// construct an empty randomized queue
public RandomizedQueue() {
rq = (Item[]) new Object[8];
size = 0;
}
// is the randomized queue empty?
public boolean isEmpty() {
return size == 0;
}
// return the number of items on the randomized queue
public int size() {
return size;
}
// add the item
public void enqueue(Item item) {
if (item == null)
throw new IllegalArgumentException();
if (size == rq.length)
resize(2 * rq.length);
rq[size++] = item;
}
// remove and return a random item
public Item dequeue() {
if (size == 0)
throw new NoSuchElementException();
if (size < rq.length / 4)
resize(rq.length / 2);
int target = StdRandom.uniform(0, size);
Item item = rq[target];
rq[target] = rq[size];
rq[size] = null;
return item;
}
// return a random item (but do not remove it)
public Item sample() {
if (size == 0)
throw new NoSuchElementException();
return rq[StdRandom.uniform(0, size)];
}
// return an independent iterator over items in random order
public Iterator<Item> iterator() {
return new RandomIterator();
}
private void resize(int capacity) {
Item[] newrq = (Item[]) new Object[capacity];
System.arraycopy(rq, 0, newrq, 0, size);
rq = newrq;
}
private class RandomIterator implements Iterator<Item> {
private int index;
private Item[] iters;
public RandomIterator() {
index = size;
iters = (Item[]) new Object[index];
System.arraycopy(rq, 0, iters, 0, size);
}
public boolean hasNext() {
return index != 0;
}
public Item next() {
if (index == 0)
throw new NoSuchElementException();
int target = StdRandom.uniform(0, index);
Item item = iters[target];
iters[target] = iters[index];
iters[index] = null;
index--;
return item;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
// unit testing (required)
public static void main(String[] args) {
}
}
Permutation.java
编写一个Permutation.java以整数k作为命令行参数的客户端程序;使用StdIn.readString(); 从标准输入读取字符串序列; 并精确地均匀地打印其中的k个。最多打印一次序列中的每个项目。
使用 RandomizedQueue 即可。写个 while 循环,很简单
public class Permutation {
public static void main(String[] args) {
RandomizedQueue<String> srq = new RandomizedQueue<>();
int k = Integer.parseInt(args[0]);
while (!StdIn.isEmpty()) {
srq.enqueue(StdIn.readString());
}
while (k > 0) {
System.out.println(srq.dequeue());
k--;
}
}
}
评分结果
有时间再改进。主要目的过完整个课程
See the Assessment Guide for information on how to interpret this report.
ASSESSMENT SUMMARY
Compilation: PASSED (0 errors, 3 warnings)
API: PASSED
Spotbugs: PASSED
PMD: FAILED (1 warning)
Checkstyle: PASSED
Correctness: 32/43 tests passed
Memory: 97/105 tests passed
Timing: 153/193 tests passed
Aggregate score: 79.74%
[Compilation: 5%, API: 5%, Spotbugs: 0%, PMD: 0%, Checkstyle: 0%, Correctness: 60%, Memory: 10%, Timing: 20%]
ASSESSMENT DETAILS
The following files were submitted:
----------------------------------
3.7K Jan 25 05:45 Deque.java
612 Jan 25 05:45 Permutation.java
2.8K Jan 25 05:45 RandomizedQueue.java
302

被折叠的 条评论
为什么被折叠?



