【泛型可迭代的基础集合数据类型的API】
背包:就是一种不支持从中删除元素的集合数据类型——它的目的就是帮助用例收集元素并迭代遍历所有收集到的元素。(用例也可以检查背包是否为空, 或者获取背包中元素的数量)
public class Bag<Item> implements Iterable<Item>
Bag() 创建一个空背包
void add(Item item) 添加一个元素
boolean isEmpty() 背包是否为空
int size() 背包中的元素数量
使用Bag的API, 用例可以将元素添加到背包,并通过foreach循环来访问所有元素。用例也可以使用栈或者队列, 但使用Bag可以说明元素的处理顺序不重要 。
先进先出(FIFO)队列:
public class Queue<Item> implements Iterable<Item>
Queue() 创建一个空队列
void enqueue(Item item) 添加一个元素
Item dequeue() 删除最近添加的元素
boolean isEmpty() 队列是否为空
int size() 队列中的元素数量
下压(后进先出,LIFO)栈
public class Stack<Item> implements Iterable<Item>
Stack() 创建一个空栈
void push(Item item) 添加一个元素
Item pop() 删除最近添加的元素
boolean isEmpty() 栈是否为空
int size() 栈中元素数量
Stats类是Bag的一个典型用例。
它的任务是简单地计算标准输入中的所有double值的平均值和样本标准差。数的计算顺序和结果无关,因此我们将它们保存在一个Bag对象中, 并使用foreach循环来计算每个和。
用Bag对象保存所有数字是更复杂的统计计算所必须的 。
背包的典型用例:Stats.java
public class Stats { public static void main(String[] args) { Bag<Double> numbers = new Bag<Double>();
while(!StdIn.isEmpty())
numbers.add(StdIn.readDouble());
int N = numbers.size();
double sum = 0.0;
for (Double x : numbers)
sum += x;
double mean = sum / N;
sum = 0.0; for (Double x : numbers)
sum += (x-mean)*(x-mean);
double std = Math.sqrt(sum/(N-1)); StdOut.printf("mean : %.2f\n", mean);
StdOut.printf("Std dev : %.2f\n", std); }
}
【打印结果】
【Bag.java】
import java.util.Iterator;
import java.util.NoSuchElementException; public class Bag<Item> implements Iterable<Item> { private int N; // number of elements in bag
private Node<Item> first; // beginning of bag // helper linked list class
private static class Node<Item> {//嵌套类
private Item item;
private Node<Item> next;
} /**
* Initializes an empty bag.
*/
public Bag() {
first = null;
N = 0;
} /**
* Is this bag empty?
* @return true if this bag is empty; false otherwise
*/
public boolean isEmpty() {
return first == null;
} /**
* Returns the number of items in this bag.
* @return the number of items in this bag
*/
public int size() {
return N;
} /**
* Adds the item to this bag.
* @param item the item to add to this bag
*/
public void add(Item item) {//由add()方法可以看出,是头插法。
Node<Item> oldfirst = first;
first = new Node<Item>();
first.item = item;
first.next = oldfirst;
N++;
} /**
* Returns an iterator that iterates over the items in the bag in arbitrary order.
* @return an iterator that iterates over the items in the bag in arbitrary order
*/
public Iterator<Item> iterator() {
return new ListIterator<Item>(first);
} // an iterator, doesn't implement remove() since it's optional
private class ListIterator<Item> implements Iterator<Item> {
private Node<Item> current; public ListIterator(Node<Item> first) {
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;
}
} /**
* Unit tests the <tt>Bag</tt> data type.
*/
public static void main(String[] args) {
Bag<String> bag = new Bag<String>();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
bag.add(item);
} StdOut.println("size of bag = " + bag.size());
for (String s : bag) {
StdOut.println(s);
}
} }
【Queue.java】
import java.util.Iterator;
import java.util.NoSuchElementException; public class Queue<Item> implements Iterable<Item> {
private int N; // number of elements on queue
private Node<Item> first; // beginning of queue
private Node<Item> last; // end of queue // helper linked list class
private static class Node<Item> {
private Item item;
private Node<Item> next;
} /**
* Initializes an empty queue.
*/
public Queue() {
first = null;
last = null;
N = 0;
} /**
* Is this queue empty?
* @return true if this queue is empty; false otherwise
*/
public boolean isEmpty() {
return first == null;
} /**
* Returns the number of items in this queue.
* @return the number of items in this queue
*/
public int size() {
return N;
} /**
* Returns the item least recently added to this queue.
* @return the item least recently added to this queue
* @throws java.util.NoSuchElementException if this queue is empty
*/
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
return first.item;
} /**
* Adds the item to this queue.
* @param item the item to add
*/
public void enqueue(Item item) {
Node<Item> oldlast = last;
last = new Node<Item>();
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last;
N++;
} /**
* Removes and returns the item on this queue that was least recently added.
* @return the item on this queue that was least recently added
* @throws java.util.NoSuchElementException if this queue is empty
*/
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = first.item;
first = first.next;
N--;
if (isEmpty()) last = null; // to avoid loitering
return item;
} /**
* Returns a string representation of this queue.
* @return the sequence of items in FIFO order, separated by spaces
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
} /**
* Returns an iterator that iterates over the items in this queue in FIFO order.
* @return an iterator that iterates over the items in this queue in FIFO order
*/
public Iterator<Item> iterator() {
return new ListIterator<Item>(first);
} // an iterator, doesn't implement remove() since it's optional
private class ListIterator<Item> implements Iterator<Item> {
private Node<Item> current; public ListIterator(Node<Item> first) {
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;
}
} /**
* Unit tests the <tt>Queue</tt> data type.
*/
public static void main(String[] args) {
Queue<String> q = new Queue<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)");
}
}
【Stack.java】
import java.util.Iterator;
import java.util.NoSuchElementException; public class Stack<Item> implements Iterable<Item> {
private int N; // size of the stack
private Node<Item> first; // top of stack // helper linked list class
private static class Node<Item> {
private Item item;
private Node<Item> next;
} /**
* Initializes an empty stack.
*/
public Stack() {
first = null;
N = 0;
} /**
* Is this stack empty?
* @return true if this stack is empty; false otherwise
*/
public boolean isEmpty() {
return first == null;
} /**
* Returns the number of items in the stack.
* @return the number of items in the stack
*/
public int size() {
return N;
} /**
* Adds the item to this stack.
* @param item the item to add
*/
public void push(Item item) {
Node<Item> oldfirst = first;
first = new Node<Item>();
first.item = item;
first.next = oldfirst;
N++;
} /**
* Removes and returns the item most recently added to this stack.
* @return the item most recently added
* @throws java.util.NoSuchElementException if this stack is empty
*/
public Item pop() {
if (isEmpty()) throw new NoSuchElementException("Stack underflow");
Item item = first.item; // save item to return
first = first.next; // delete first node
N--;
return item; // return the saved item
} /**
* Returns (but does not remove) the item most recently added to this stack.
* @return the item most recently added to this stack
* @throws java.util.NoSuchElementException if this stack is empty
*/
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Stack underflow");
return first.item;
} /**
* Returns a string representation of this stack.
* @return the sequence of items in the stack in LIFO order, separated by spaces
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
} /**
* Returns an iterator to this stack that iterates through the items in LIFO order.
* @return an iterator to this stack that iterates through the items in LIFO order.
*/
public Iterator<Item> iterator() {
return new ListIterator<Item>(first);
} // an iterator, doesn't implement remove() since it's optional
private class ListIterator<Item> implements Iterator<Item> {
private Node<Item> current; public ListIterator(Node<Item> first) {
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;
}
} /**
* Unit tests the <tt>Stack</tt> data type.
*/
public static void main(String[] args) {
Stack<String> s = new Stack<String>();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
if (!item.equals("-")) s.push(item);
else if (!s.isEmpty()) StdOut.print(s.pop() + " ");
}
StdOut.println("(" + s.size() + " left on stack)");
}
}
【Queue测试用例 QueueCase.java】
public class QueueCase { public static void main(String[] args) { int[] temp = readInts(name);
for (int i = 0; i < temp.length; i++)
System.out.println(temp[i] + " ");
} public static int[] readInts(String name){
In in = new In(name);
Queue<Integer> q = new Queue<Integer>();
while(!in.isEmpty())
q.enqueue(in.readInt());
int N = q.size();
int[] a = new int[N];
for (int i = 0; i < N; i++)
a[i] = q.dequeue();
return a;
}
}
【Stack 测试用例 StackCase.java】
public class StackCase { public static void main(String[] args) { In in = new In(args[0]);
Stack<Integer> s = new Stack<Integer>();
while(!StdIn.isEmpty())
s.push(StdIn.readInt());
for (int i : s) {
System.out.println(i + " ");
}
}
}