栈-Stack
栈是一种先入后出的限定性线性表。
数据的插入和删除操作仅在同一端进行,称为栈顶(top),另一端为固定的一端,称为栈底(Bottom)。
特征是先入后出。
栈有两种基本操作push进栈(栈顶插入)和pop出栈(删除栈顶),基本实现有数组(顺序栈)和链表(链式栈)。
顺序栈的实现
System.arraycopy(src, srcPos, dest, destPos, length);可实现动态扩容
public class ArrayStack{//泛型或Object类
private String [] items;//数组用于存储数据
private int count;//记录栈中的元素个数
public ArrayStack(int capacity) {
items=new String[capacity];
count=0;
}
public boolean push(String item) {
if (count == items.length)
return false;//存储空间不足,直接返回false告知入栈失败
items[count++]=item;
return true;
}
public String pop() {
if (count==0) {
return null;//栈为空直接返回null
}
return items[--count];
}
}
Stack类
JDK中提供了一个堆栈类Stack,继承了Vector,提供了常见的push和pop操作
已经不再建议使用,可以使用更完善、可靠性更强的LIFO操作由Deque接口和它的实现
Deque接口
Deque接口的常见数组实现为ArrayDeque
Stack<Integer> stack = new Stack<Integer>();
Deque<Integer> stack1 = new ArrayDeque<>();
for (int i = 0; i < 5; i++) {
stack1.push(i);
}
System.out.println("size:"+stack1.size());
for (int i = 0; i < 5; i++) {
System.out.println(stack1.pop());
}
System.out.println("size:"+stack1.size());
队列Queue
队列是一种操作受限的线性表,在表的前端进行删除操作,在表的后端进行插入操作;两种基本操作入队enqueue和出队dequeue。特征FIFO先进先出,根据不同的实现方式可以分为顺序队列和链式队列。
模拟顺序队列
public class ArrayQueue {
private String [] items;
private int head=0;//队列头部
private int tail=0;//队列尾部
public ArrayQueue(int capacity) {
items=new String[capacity];
}
public boolean enqueue(String item) {
if (tail==items.length) {
return false;//队列已满
}
items[tail++]=item;
return true;
}
public String dequeuq() {
if (head==tail) {//队列为空
return null;
}
return items[head++];
}
}
Queue接口
JDK中提供了Queue队列接口,表示一个FIFO的数据结构
add和offer在队列尾部新增数据。一个满的队列中加入新数据,多出的数据项就会被拒绝。add抛异常,而offer返回false。
poll和remove从队列头部删除数据,当队列为空时remove同Collection接口定义,poll只是返回null。
peek和element在队列头部查询元素,当队列为空时element抛出异常,而peek返回null
循环队列
public class Circlequeue {
private String[] items;
private int head = 0;
private int tail = 0;
public Circlequeue(int capacity) {
items = new String[capacity];
}
public boolean enqueue(String item) {
//判断队列存储已经到达上限
if ((tail + 1) % items.length == head)
return false;
items[tail] = item;
// 循环的体现,到达数组的末尾再从头开始
tail = (tail + 1) % items.length;
return true;
}
public String dequeue() {
if (head == tail)
return null;
String res = items[head]; // 获取头指针指向的数据
head = (head + 1) % items.length;
return res;
}
}
常见的非阻塞队列
ArrayDeque数组实现的两倍自动扩容的双端队列,其中addFirst和addLast体现双端的特性
ConcurrentLinkedQueue基于链表的并发队列
PriorityQueue优先级队列
阻塞队列
BlockingQueue接口针对插入、移除、获取元素提供了不同的方法用于应对不同的场景
1.抛出异常
2.返回特殊值,例如null或true/false
3.阻塞操作
4.阻塞等待超时
具体实现
ArrayBlockingQueue基于数组的并发阻塞队列,底层是数组,有界队列
LinkedBlockingQueue基于链表的FIFO阻塞队列,底层是链表,可以当作有界或者无界队列
PriorityBlockingQueue带优先级的无界阻塞队列,基于数组的二叉树
SynchronousQueue并发同步阻塞队列,不存储任何元素,可以选择公平模式和非公平模式