开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情
在之前写过一次:手动实现队列 - 掘金 (juejin.cn)
本次在上一次基础上,按照源码进行分析讲解。 我们通常使用队列是这样的
Queue<Integer> queue=new LinkedList<Integer>();
点进:queue,显示如下
Inserts那一句:翻译后如下:
如果在不违反容量限制的情况下立即将指定元素插入此队列,则在成功时返回true,如果当前没有可用空间,则抛出IllegalStateException。
后面列举了参数,返回值和可能出现的异常
再往下:我们可以发现队列的方法:
boolean add(E e);添加元素,如果队列满了,抛出异常
boolean offer(E e);添加元素,如果队列满了,返回false
E remove();将首个元素从队列中弹出,如果队列是空的,就返回null
E poll();移除元素
E element();查看首个元素,不会移除首个元素,如果队列是空的就抛出异常NoSuchElementException
E peek();查看首个元素,不会移除首个元素,如果队列是空的就返回null
首先,我们需要关注第一个:队列大小?通过前面源码,我们自动队列继承了Collection<E>点击Collection<E>
可以发现,在Collection里面还有一些方法: 比如获取长度的 size() 方法,判断是不是为null的 isEmpty(),判断是不是包含某元素的:boolean contains(Object o)等。
我们知道队列为一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出线性表。
在右边实现类,我们使用的LinkedList,具体参考Collection和Map - 掘金 (juejin.cn)。在这里,即声明了队列底层数据结构
java队列底层是链表实现的。 所以实现起来比较简单:声明一个链表,和一个标兵(用来模拟指针,进行一个定位操作)
public class MyQueue{
private List<Integer> list;
private p_start;
public MYQueue(){
list=new ArrayList<Integer>();
p_start=0;
}
public boolean addQueue(int x){
list.add(x);
return true;
}
public boolean delQueue(){
if(list.size()<=p_start){
reyturn false;
}
p_start++;
return true;
}
public boolean font(){
return list.get(p_start);
}
}
循环队列实现
在我们直接定义使用队列的时候,需要指定元素个数element,若存入的元素致使个数超出数组限制,则需要将 element 数组的容量扩展至从前容量的两倍。如果个数太少,会导致存储空间的浪费,为了解决浪费问题,循环队列出现了
我们可以使用固定大小的数组和两个指针来指示起始位置和结束位置。 目的是重用被浪费的存储。
入队:队尾指针加1取模,Q.rear=(Q.rear+1)%MaxSize;
出队:队头指针加1取模,Q.front=(Q.front+1)%MaxSize;
入队:队尾指针加1取模,Q.rear = (Q.rear + 1) % MaxSize;
队满:队尾指针加1取模等于队头指针,(Q.rear + 1) % MaxSize=Q.front;
队空:Q.front=Q.rear;
队中元素个数:(Q.rear-Q.front+MaxSize)%MaxSize;
确定了这些之后,我们可以开始写代码:
使用的变量:
int[] num=new int[k+1]; int head=0; int tail=0;
判断是不是队列满了:
public boolean isFull() {
if( (tail+1)%num.length==head){
return true;
}
return false;
}
判断是不是队空:
public boolean isEmpty() {
if(head==tail){
return true;
}
return false;
}
向队列添加元素:
public boolean enQueue(int value) {
if(isFull()){
return false;
}
else{
num[tail] =value;
tail=(tail+1)%num.length;
return true;
}
}
从队列删除元素:
public boolean deQueue() {
if(!isEmpty()){
head=(head+1)%num.length;
return true;
}
return false;
}
获取首元素:
获取尾元素: