泛型双端队列和随机队列
参考了5262yz和u013685323的博客,感谢
Java泛型
- Java不允许创建泛型数组实例,需要强制类型转换:泛型采用擦除(Erasure)实现,运行时类型参数会被擦掉(实际元素都是Object),导致数组赋值时,类型产生错误。
但是java可以强制转换原生类型,即可以声明一个泛型数组的引用:(T [ ])迭代器
- 接口iterable:张小琦介绍了iterable和iterator的区别。简单地说,客户端遍历所有元素,但不关心迭代器的内部实现。
Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。
- 接口iterator:实现iterable接口,可根据客户端需要的准则在内部类中继承的iterator接口并设计方法。调用iterator()方法时,返回内部类的实例,完成遍历功能。主要方法hasNext(), next()
数组实现栈结构
- 游离:pop() 类型的操作中,避免 return s[–n] 的使用。此时该元素已经出栈,然而内存中仍有其指针(旧元素的指针),不能充分利用内存。采用如下方式:
item = s[--n] s[n] = null return item
- 可变的数组大小:反复倍增(repeat doubling)。一种合理的方法:当数组满,数组大小翻倍并copy数组所有元素。当数组减小到长度的 1/4 1 / 4 ,减半数组长度。
Codes
Deque 用链表结构
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Deque<Item> implements Iterable<Item> {
private int n;
private Node first;
private Node last;
// helper linked list class
private class Node {
private Item item;
private Node next;
private Node prev;
}
public Deque() {
first = null;
last = first;
n = 0;
}
public boolean isEmpty() {
return n == 0;
}
public int size() {
return n;
}
public void addFirst(Item item) {
if (item == null)
throw new IllegalArgumentException();
Node oldfirst = first;
first = new Node();
first.item = item;
first.prev = null;
if (isEmpty()) {
last = first;
first.next = null;
} else {
first.next = oldfirst;
oldfirst.prev = first;
}
n++;
}
public void addLast(Item item) {
if (item == null)
throw new IllegalArgumentException();
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()) {
first = last;
last.prev = null;
} else {
last.prev = oldlast;
oldlast.next = last;
}
n++;
}
public Item removeFirst() {
if (isEmpty())
throw new NoSuchElementException();
Item item = first.item;
first = first.next;
n--;
if (isEmpty()) last = first = null;
else first.prev = null;
return item;
}
public Item removeLast() {
if (isEmpty())
throw new NoSuchElementException();
Item item = last.item;
last = last.prev;
n--;
if (isEmpty()) last = first = null;
else last.next = null;
return item;
}
public Iterator<Item> iterator() {
return new DequeIterator();
}
private class DequeIterator implements Iterator<Item> {
private Node current = first;
public boolean hasNext() {
return current != null;
}
public boolean hasPre() {
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;
}
}
}
RandomizedQueue 采用数组结构
import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class RandomizedQueue<Item> implements Iterable<Item> {
private Item[] s;
private int n = 0;
public RandomizedQueue() {
s = (Item[]) new Object[1];
}
private void resize(int capacity) {
Item[] copy = (Item[]) new Object[capacity];
for (int i = 0; i < n; i++)
copy[i] = s[i];
s = copy;
}
public boolean isEmpty() {
return n == 0;
}
public int size() {
return n;
}
public void enqueue(Item item) {
if (item == null) {
throw new IllegalArgumentException();
}
if (n == s.length) resize(2 * s.length);
s[n++] = item;
}
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException();
int ranId = StdRandom.uniform(n);
Item item = s[ranId];
s[ranId] = s[n-1];
s[--n] = null;
if (n > 0 && n == s.length / 4) resize(s.length / 2);
return item;
}
public Item sample() {
if (isEmpty()) throw new NoSuchElementException();
int id = StdRandom.uniform(n);
return s[id];
}
public Iterator<Item> iterator() {
return new RandQueIterator();
}
private class RandQueIterator implements Iterator<Item> {
private final int[] randomIndex = StdRandom.permutation(n);
private int i = 0;
public boolean hasNext() { return i < n; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
return s[randomIndex[i++]];
}
}
}
这次的练习对java泛型和迭代器有了更好的认识