初识背包、队列和栈及其应用
接下来一起了解下三种非常基础且应用广泛的数据结构:背包(Bag)、队列(Queue)和栈(Stack)。
背包
什么是背包?
背包是一种不支持从中删除元素的集合数据类型,它的目的就是帮助用例收集元素并迭代遍历所有收集到的元素,迭代的顺序不确定且与用例无关。
顾名思义,可以想象它是一个背包,里面可以放很多东西,东西的顺序不太重要……书本中给出了一个算平均数的背包用例,给大家展示一下。它似乎是很有用的?但我刚刚学习完竟不知道它会在哪发挥作用,不过看到有这个基础的“01背包问题”,啊先继续学习下去,不必囫囵吞枣。
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;
// foreach语法来计算和
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);
}
}
队列
队列也叫 先进先出(FIFO) 队列,元素的处理顺序就是它们被添加到队列的顺序,使他们入列顺序和出列顺序相同。可以想想排队就好啦,那是一模一样的。
下面展示一段代码,把队列中的所有整数按顺序移动到数组里面,
public static int [] readInts(String name){
In in = new In(name);
Queue<Integer> q = new Queue<>();
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;
}
PS:在这些你还会发现我们不用事先知道输入的文件大小而提前准备数组大小,直接将文件中的所有整数读入一个数组中去。
栈
栈也叫下压栈, 是一种基于**后进先出(LIFO)**策略的集合类型。举一个电子邮件的例子,收信时将压入(push)最顶端,取信时从最顶端将它们弹出(pop),第一封信总是最新的(后进,则先出)。下面的代码写的是将输入的整数逆序输出
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
while(!StdIn.isEmpty()) {
stack.push(StdIn.readInt());
}
for(int i : stack) {
StdOut.println(i);
}
}
PS:这个小例子也有一个巧妙之处噢,它不用预先知道整数的多少。