手写队列

61 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

在之前写过一次:手动实现队列 - 掘金 (juejin.cn)

本次在上一次基础上,按照源码进行分析讲解。 我们通常使用队列是这样的

Queue<Integer> queue=new LinkedList<Integer>();

点进:queue,显示如下

image.png 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>

image.png

可以发现,在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;
    }

获取首元素:

image.png

获取尾元素:

image.png