背包、队列和栈

API

背包
public class Bag implements Iterable
Bag() 创建一个空背包
void add(Item item) 添加一个元素
boolean isEmpty() 背包是否为空
int size() 背包中的元素数量
先进先出(FIFO)队列
pubilc class Queue implements Iterable
Queue() 创建空队列
void enqueue(Item item) 添加一个元素
Item dequeue() 删除最早添加的元素
boolean isEmpty() 队列是否
int size() 队列中元素的数量
下压(后进先出,LIFO)栈
public class Stack implements Iterable
Stack() 创建一个空栈
void push(Item item) 添加一个元素
Item pop() 删除最近添加的元素
boolean isEmpty() 栈是否为空
int size() 栈中的元素数量

背包

背包是一种不支持从中删除元素的集合数据类型——它的目的就是帮助用例手机元素并迭代遍历所有收集到的元素,迭代的顺序不确定并且与用例无关。

典型用例:求平均值和方差

public class Statas {

	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", mean);
		StdOut.printf("Std dev: %.2f\n", std);
	}
}

先进先出队列

先进先出队列(或简称队列)是一种基于先进先出(FIFO)策略的集合类型。

生活中的例子:在影剧院门前排队的人群、在收费站前排队的汽车或是计算机上某种软件中等待处理的任务。

用例:

public static void main(String[] args) {
  	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;
}

下压栈

下压栈(或简称栈)是一种基于后进先出(LIFO)策略的集合类型。

生活中的例子:桌上的邮件,新邮件到来的时将它们放在最上面,有空时会一封一封地从上到下拿信件阅读。

用例:

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.pop();
		}
	}
}

栈的应用:算数表达式求值

用两个栈,一个用于保存运算符,一个用于保存操作数。

  • 将操作数压入操作数栈
  • 将运算符压入运算符栈
  • 忽略左括号
  • 在遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结构压入操作数栈

在处理完最后一个右括号时,操作数栈上只会有一个值,它就是表达式的值。

public class Evaluate {
	public static void main(String[] args) {
		Stack<String> ops = new Stack<String>();
		Stack<Double> vals = new Stack<Double>();
		while (!StdIn.isEmpty()) {
			// 读取字符,如果是运算符则压入栈
			String s = StdIn.readString();
			if (s.equals("(")) {
				;
			} else if (s.equals("+")) {
				ops.push(s);
			} else if (s.equals("-")) {
				ops.push(s);
			} else if (s.equals("*")) {
				ops.push(s);
			} else if (s.equals("/")) {
				ops.push(s);
			} else if (s.equals("sqrt")) {
				ops.push(s);
			} else if (s.equals(")") {
				// 如果字符为 ")",弹出运算符和操作数,计算结果压入操作数栈
				String op = ops.pop();
				double v = vals.pop();
				if (op.equals("+")) {
					v = vals.pop() + v;
				} else if (op.equals("-")) {
					v = vals.pop() - v;
				} else if (op.equals("*")) {
					v = vals.pop() * v;
				} else if (op.equals("/")) {
					v = vals.pop() / v;
				} else if (op.equals("sqrt")) {
					v = Math.sqrt(v);
				}
				vals.push(v);
			} else {
				// 如果字符既非运算符也不是括号,将它作为 double 值压入操作数栈
				vals.push(Double.parseDouble(s));
			}
		}
		StdOut.println(vals.pop());
	}
}
posted @ 2016-09-27 21:51  勇敢的少年啊  阅读(157)  评论(0编辑  收藏  举报