设计循环队列

Kubernetes舵手
• 阅读 757

循环队列是表示内部是循环的,但操作依然是只能往队尾添加元素,但各项操作优化到O(1)。

这是接口设计

public class CircleQueue<E> {
    // 记录第0个元素的索引
    private int front;
    // 当前队列存储的元素个数
    private int size;
    // 用来存储元素的数组
    private E[] elements;
    // 当前队列存储的元素数量
    public int size();
    // 当前队列是否为空
    public boolean isEmpty();
    // 入队
    public void enQueue(E element);
    // 出队
    public E deQueue();
    // 查看索引为0的元素
    public E front();
}

这里只介绍几个重要的方法。
入队:
首先需要判断数组是否需要扩容

private void ensureCapacity(int capacity) {
    int oldCapacity = elements.length;
    if (oldCapacity >= capacity) return;
        
    // 新容量为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1); //位运算
    E[] newElements = (E[]) new Object[newCapacity];
    for (int i = 0; i < size; i++) {
        newElements[i] = elements[index(i)];
    }
    elements = newElements;
        
    // 重置front
    front = 0;
}

然后计算在数组中入队的索引

  • 预期入队索引 = 第0个元素索引 + 当前队列元素个数
  • 如果预期入队索引大于等于数组长度实际入队索引 = 预期入队索引 - 数组长度
  • 如果预期入队索引小于数组长度实际入队索引 = 预期入队索引
private int index(int index) {
    index += front;
    return index - (index >= elements.length ? elements.length : 0);
}

所以入队的方法为

public void enQueue(E element) {
    // 数组扩容判断,要加新元素,需要的容量就是当前容量加一
    ensureCapacity(size + 1);
    // 索引计算,并赋值
    elements[index(size)] = element;
    // size加一
    size++;
}

出队,就移动front指针

public E deQueue() {
    // 获取出队元素
    E frontElement = elements[front];
    // 将索引位置致空
    elements[front] = null;
    // 更新font,这里参数为1
    front = index(1);
    // size减一
    size--;
    // 返回出队元素
    return frontElement;
}

至此,循环队列的方法就介绍完了。值得探讨的是index这个方法,很精妙。
这篇文章参考了小码哥的笔记,附上链接
参考博文

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java实现队列的详细代码
一、什么是队列结构一种线性结构,具有特殊的运算法则【只能在一端(队头)删除,在另一端(队尾)插入】。分类:1.顺序队列结构2.链式队列结构基本操作:1.入队列2.出队列  二:准备数据staticfinal intQUEUELEN15;classDATA{          String
菜园前端 菜园前端
2年前
什么是宏任务与微任务?
原文链接:事件循环机制在事件循环中,每进行一次循环操作称为tick,每一次tick的任务处理是比较复杂的。关键步骤如下:1.执行一个宏任务2.执行过程中如果遇到微任务,就将它添加到微任务的任务队列中3.宏任务执行完毕后,立即执行当前微任务队列中的所有微任务
Stella981 Stella981
3年前
C++ 优先队列priority_queue用法
头文件:include<queue操作:top访问队头empty队列是否为空size返回队列元素个数push插入元素到队尾pop弹出队头swap交换内容定义:1/2Type数据类型3Container容器类型(必须是vect
Stella981 Stella981
3年前
LinkedBlockingQueue 介绍
LinkedBlockingQueue是一个基于已链接节点的、范围任意的blockingqueue。此队列按FIFO(先进先出)排序元素。队列的头部是在队列中时间最长的元素。队列的尾部是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可
Stella981 Stella981
3年前
Android消息循环分析
我们的常用的系统中,程序的工作通常是有事件驱动和消息驱动两种方式,在Android系统中,Java应用程序是靠消息驱动来工作的。消息驱动的原理就是:1\.有一个消息队列,可以往这个队列中投递消息;2\.有一个消息循环,不断从消息队列中取出消息,然后进行处理。在Android中通过Looper来封装消息循环,同时在其中封装了一个消息队
Stella981 Stella981
3年前
ConcurrentQueue队列的基本使用方式
 队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。  ConcurrentQueue<T队列是一个高效的线程安全的队列,是.NetFramework4.0,System.Collections.Concurren
Wesley13 Wesley13
3年前
JAVA中循环删除list中元素的方法总结
印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区。下面就来讲一讲。。伸手党可直接跳至文末。看总结。。  JAVA中循环遍历list有三种方式for循环、增强for循环(也就是常说的foreach循环)、iterator遍历。1、for循环遍
Wesley13 Wesley13
3年前
JAVA线程15
一、阻塞队列1\.概述阻塞队列是Java5线程新特征中的内容,Java定义了阻塞队列的接口java.util.concurrent.BlockingQueue。阻塞队列是一个指定长度的队列,如果队列满了,添加新元素的操作会被阻塞等待,直到有空位为止。同样,当队列为空时候,请求队列元素的操作同样会阻塞等待,直到有可用元
Wesley13 Wesley13
3年前
Java并发 阻塞队列
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加操作支持阻塞地插入和移除方法。支持阻塞插入的方法是指当队列满时会阻塞插入元素的线程,直到队列不满;支持阻塞移除的方法是指当队列为空时获取元素的线程无法继续获取元素直到队列不空。可以发现阻塞队列非常适合消费者和生产者场景下进行使用,生产者生产数据就是向阻塞队列中插入元素,消费者消
Wesley13 Wesley13
3年前
PHP优先级队列
优先级队列首先,我们要了解一下什么叫队列:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。从定义来看,队列是无法更改顺序的线性集合。线性集合一般有几种规则:先进先出(队
菜园前端 菜园前端
2年前
什么是队列
原文链接:什么是队列?队列是一种遵循先进先出原则的有序集合,添加新元素的一端称为队尾,另一端称为队首。实现功能在JavaScript中没有队列,但是可以通过Array实现队列的所有功能enqueue()入队dequeue()出队top()获取队首值size
Kubernetes舵手
Kubernetes舵手
Lv1
已经在原地冲你的背影挥累了手
文章
4
粉丝
0
获赞
0