前言
正文
API
Bag
Bag() create an empty bag
void add(Item item) add an item
boolean isEmpty() is the bag empty?
int size() number of items in the bag
FIFO queue
Queue() create an empty queue
void enqueue(Item item) add an item
Item dequeue() remove the least recently added item
boolean isEmpty() is the queue empty?
int size() number of items in the queue
Pushdown (LIFO) stack
Stack() create an empty stack
void push(Item item) add an item
Item pop() remove the most recently added item
boolean isEmpty() is the stack empty?
int size() number of items in the stack
介绍
背包
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);
}
}
% java Stats
100
99
101
120
98
107
109
81
101
90
Mean: 100.60
Std dev: 10.51
先进先出队列
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;
}
下压栈
public class Reverse
{
public static void main(String[] args)
{
Stack<Integer> stack;
stack = new Stack<Integer>();
while (!StdIn.isEmpty())
stack.push(StdIn.readInt());
for (int i : stack)
StdOut.println(i);
}
}
集合类数据类型的实现
定容栈(FixedCapacityStackofStrings)
定容栈的API
FixedCapacityStackOfStrings(int cap) create an empty stack of capacity cap
void push(String item) add a string
String pop() remove the most recently added string
boolean isEmpty() is the stack empty?
int size() number of strings on the stack
public static void main(String[] args)
{
FixedCapacityStackOfStrings s;
s = new FixedCapacityStackOfStrings(100);
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)");
}
% more tobe.txt
to be or not to - be - - that - - - is
% java FixedCapacityStackOfStrings < tobe.txt
to be not that or be (2 left on stack)
public class FixedCapacityStackOfStrings
{
private String[] a; // stack entries
private int N; // size
public FixedCapacityStackOfStrings(int cap)
{ a = new String[cap]; }
public boolean isEmpty() { return N == 0; }
public int size() { return N; }
public void push(String item)
{ a[N++] = item; }
public String pop()
{ return a[--N]; }
}
泛型
API
void push(Item item) add an item
Item pop() remove the most recently added item
boolean isEmpty() is the stack empty?
int size() number of items on the stack
public static void main(String[] args)
{
FixedCapacityStack<String> s;
s = new FixedCapacityStack<String>(100);
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)");
}
% more tobe.txt
to be or not to - be - - that - - - is
% java FixedCapacityStack < tobe.txt
to be not that or be (2 left on stack)
public class FixedCapacityStack<Item>
{
private Item[] a; // stack entries
private int N; // size
public FixedCapacityStack(int cap)
{ a = (Item[]) new Object[cap]; }
public boolean isEmpty() { return N == 0; }
public int size() { return N; }
public void push(Item item)
{ a[N++] = item; }
public Item pop()
{ return a[--N]; }
}
private void resize(int max)
{ // Move stack of size N <= max to a new array of size max.
Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < N; i++)
temp[i] = a[i];
a = temp;
}
public void push(String item)
{ // Add item to top of stack.
if (N == a.length) resize(2*a.length);
a[N++] = item;
}
类似,在pop()中,首先删除站定元素,然后如果数组太大我们就将它的长度减半。只要稍加思考,你就明白正确的检测条件是栈大小是否小于数组的四分之一。在数组长度减半之后,它的状态约为半满,在下次需要改变数组大小之前仍让能够进行多次的push()和pop()操作。
public String pop()
{ // Remove item from top of stack.
String item = a[--N];
a[N] = null; // Avoid loitering (see text).
if (N > 0 && N == a.length/4) resize(a.length/2);
return item;
}
Stack<String> collection = new Stack<String>();
...
for (String s : collection)
StdOut.println(s);
...
这里实际上用到的是Iterator的简写,即:
Iterator<String> i = collection.iterator();
while (i.hasNext())
{
String s = i.next();
StdOut.println(s);
}
也就是说,在任意可迭代的集合数据类型中,我们都要实现:
- 集合数据类型不需实现一个iterator()方法并返回一个Iterator对象
- Iterator类必须包含两个方法:hasNext(),next()。分别用来:返回一个bool值和返回集合中的一个泛型元素。
public interface Iterator<Item>
{
boolean hasNext();
Item next();
void remove();
}
private class ReverseArrayIterator implements Iterator<Item>
{
private int i = N;
public boolean hasNext() { return i > 0; }
public Item next() { return a[--i]; }
public void remove() { }
}
/************************************************************************* * Compilation: javac ResizingArrayStack.java * Execution: java ResizingArrayStack < input.txt * Data files: http://algs4.cs.princeton.edu/13stacks/tobe.txt * * Stack implementation with a resizing array. * * % more tobe.txt * to be or not to - be - - that - - - is * * % java ResizingArrayStack < tobe.txt * to be not that or be (2 left on stack) * *************************************************************************/ import java.util.Iterator; import java.util.NoSuchElementException; /** * The ResizingArrayStack class represents a last-in-first-out (LIFO) stack * of generic items. * It supports the usual push and pop operations, along with methods * for peeking at the top item, testing if the stack is empty, and iterating through * the items in LIFO order. *
* This implementation uses a resizing array, which double the underlying array * when it is full and halves the underlying array when it is one-quarter full. * The push and pop operations take constant amortized time. * The size, peek, and is-empty operations takes * constant time in the worst case. *
* For additional documentation, see Section 1.3 of * Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne. * * @author Robert Sedgewick * @author Kevin Wayne */ public class ResizingArrayStack implements Iterable { private Item[] a; // array of items private int N; // number of elements on stack /** * Initializes an empty stack. */ public ResizingArrayStack() { a = (Item[]) new Object[2]; } /** * Is this stack empty? * @return true if this stack is empty; false otherwise */ public boolean isEmpty() { return N == 0; } /** * Returns the number of items in the stack. * @return the number of items in the stack */ public int size() { return N; } // resize the underlying array holding the elements private void resize(int capacity) { assert capacity >= N; Item[] temp = (Item[]) new Object[capacity]; for (int i = 0; i < N; i++) { temp[i] = a[i]; } a = temp; } /** * Adds the item to this stack. * @param item the item to add */ public void push(Item item) { if (N == a.length) resize(2*a.length); // double size of array if necessary a[N++] = item; // add item } /** * 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 = a[N-1]; a[N-1] = null; // to avoid loitering N--; // shrink size of array if necessary if (N > 0 && N == a.length/4) resize(a.length/2); return 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 a[N-1]; } /** * 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 iterator() { return new ReverseArrayIterator(); } // an iterator, doesn't implement remove() since it's optional private class ReverseArrayIterator implements Iterator { private int i; public ReverseArrayIterator() { i = N; } public boolean hasNext() { return i > 0; } public void remove() { throw new UnsupportedOperationException(); } public Item next() { if (!hasNext()) throw new NoSuchElementException(); return a[--i]; } } /** * Unit tests the Stack data type. */ public static void main(String[] args) { ResizingArrayStack s = new ResizingArrayStack (); 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)"); } }
链表
定义
结点记录
private class Node
{
Item item;
Node next;
}
一个Node对象含有两个实例变量,类型分别为Item(参数类型)和Node。我们会在需要使用Node类的类中定义并将它标记为private,因为他不是为用例准备的。
举例
在表头插入结点
从表头删除结点
其他位置的插入和删除
遍历
{
// Process x.item.
}
栈的实现
public class Stack<Item> implements Iterable<Item>
{
private Node first; // top of stack (most recently added node)
private int N; // number of items
private class Node
{ // nested class to define nodes
Item item;
Node next;
}
public boolean isEmpty() { return first == null; } // Or: N == 0.
public int size() { return N; }
public void push(Item item)
{ // Add item to top of stack.
Node oldfirst = first;
first = new Node();
first.item = item;
first.next = oldfirst;
N++;
}
public Item pop()
{ // Remove item from top of stack.
Item item = first.item;
first = first.next;
N--;
return item;
}
}
测试代码:
public static void main(String[] args)
{ // Create a stack and push/pop strings as directed on StdIn.
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)");
}
队列的实现
public class Queue<Item> implements Iterable<Item>
{
private Node first; // link to least recently added node
private Node last; // link to most recently added node
private int N; // number of items on the queue
private class Node
{ // nested class to define nodes
Item item;
Node next;
}
public boolean isEmpty() { return first == null; } // Or: N == 0.
public int size() { return N; }
public void enqueue(Item item)
{ // Add item to the end of the list.
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last;
N++;
}
public Item dequeue()
{ // Remove item from the beginning of the list.
Item item = first.item;
first = first.next;
if (isEmpty()) last = null;
N--;
return item;
}
}
测试代码
public static void main(String[] args)
{ // Create a queue and enqueue/dequeue strings.
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)");
}
背包的实现
import java.util.Iterator;
public class Bag<Item> implements Iterable<Item>
{
private Node first; // first node in list
private class Node
{
Item item;
Node next;
}
public void add(Item item)
{ // same as push() in Stack
Node oldfirst = first;
first = new Node();
first.item = item;
first.next = oldfirst;
}
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() { }
public Item next()
{
Item item = current.item;
current = current.next;
return item;
}
}
}
总结
后记
代码来源
- http://algs4.cs.princeton.edu/code/