背包(Bag)、队列(Queue)、下压栈(Stuck)是基础数据类型集合的三种类型,他们的区别在于删除或者访问对象的顺序不同。
背包
背包是一种不支持从中删除元素的集合数据类型,它的作用就是帮助用例收集元素并迭代遍历所有收集到的元素。
具体实现:
/**
* 背包
* @author xiaoqi
*
* @param <Item>
*/
public class Bag<Item> {
private Node node;
private class Node{
Item item;
Node next;
}
//和Stuck的push一样
public void add(Item item){
Node oldFirst = node;
node = new Node();
node.item = item;
node.next = oldFirst;
}
}
队列
队列是一种基于先进先出策略的集合类型。就好比排队一样,先到的人,先结束工作出去。它们的入列顺序和出列顺序相同。
如下所示,它将队列表示为一条从最早插入的元素到最近插入元素的链表,first指向队列的开头,last指向队列的结尾。每将一个元素入列(enqueue),就将它加入到表尾;要将一个元素出列(dequeue),就要删除表头节点。
/**
* 先进先出的队列
* @author xiaoqi
*
* @param <Item>
*/
public class Queue<Item> {
private Node first;//最早添加节点的链接
private Node last;//最近添加的节点
private int N;
private class Node{
Item item;
Node next;
}
private boolean isEmpty(){
return first==null;
}
private int size(){
return N;
}
//加入队列
public void enqueue(Item item){
Node oldFirst = last;
last = new Node();
last.item = item;
last.next = null;
if(isEmpty()){
first = last;
}else{
oldFirst.next = last;
}
N++;
}
//删除
public Item dequeue(){
if(isEmpty()){
return null;
}else{
Item item = first.item;
first = first.next;
N--;
return item;
}
}
}
栈
下压栈是一种基于后进先出策略的集合类型,元素处理顺序和它们被压入的顺序刚好相反。就如同纸一样,我们一张一张放上去,当我们要拿出来的时候,肯定从最顶部开始拿,如果上面的没有被拿掉,下面的永远不会拿到。
例如 (1+(2+3)*5)
操作过程:
1、将操作数压入操作数栈
2、将运算符压入运算符栈
3、忽略左括号
4、遇到右括号,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈。
实现栈的两种方式:
基于数组实现(ArrayList)
优点:1、每项操作的用时都和集合的大小无关
2、空间需求总是不超过集合大小乘以一个常数
/**
* 栈 动态调整数组大小的实现
* @author xiaoqi
*
* @param <Item>
*/
public class ResizingArrayStack<Item>{
private Item[] a= (Item[]) new Object[1];//通过强转,让数组泛型
private int N;//元素个数
//通过元素个数判断栈是否为空
public boolean isEmpty(){
return N==0;
}
//返回栈中元素个数
public int size(){
return N;
}
//动态调整数组大小
private void resize(int max){
Item[] temp = (Item[]) new Object[max];
//将所有数据复制到新的数组
for(int i=0;i<N;i++){
temp[i] = a[i];
}
//指向新的引用
a = temp;
}
//添加元素到栈顶
public void push(Item item){
if(N == a.length){
//当数组大小充满时,扩大数组大小为两倍
resize(2*a.length);
}
a[N++] = item;
}
//从栈顶删除元素
public Item pop(){
Item item = a[--N];
a[N] = null;//避免对象游离(无引用对象)
if(N > 0 && N == a.length/4){
//当数组大小为总长度4分之1时,调整数组大小为原长度一半
resize(a.length/2);
}
return item;
}
public Iterator<Item> iterator(){
return new ReverseArrayIterator();
}
private class ReverseArrayIterator implements Iterator<Item>{
private int i=N;
@Override
public boolean hasNext() {
return i > 0;
}
@Override
public Item next() {
return a[--i];
}
}
}
基于链表实现(LinkedList):
优点:1、所需空间总是和集合的大小成正比
2、操作的时间总和集合的大小无关
/**
* 栈 通过链表实现
* @author xiaoqi
*
* @param <Item>
*/
public class Stack<Item> {
private Node first;//栈顶元素(最近添加的元素)
private int N;
private class Node{
Item item;
Node next;
}
//通过元素个数判断栈是否为空
public boolean isEmpty(){
return first==null;
}
//返回栈中元素个数
public int size(){
return N;
}
//压入栈顶
public void push(Item item){
Node oldFirst = first;
first = new Node();
first.item = item;
first.next = oldFirst;
N++;
}
//删除栈顶元素
public Item pop(){
Item item = null;
if(!isEmpty()){
item = first.item;
first = first.next;
N--;
}
return item;
}
}