队列是一种特殊的线性表,是一种先进先出的数据结构。只允许在表的前端进行删除操作,在表的后端进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

简单的循环队列实现比较容易,队头获取数据、队头弹出获取数据,队尾插入数据。下面来研究一下可以无限循环使用的队列。思路如下:

1、数据结构

int[] elements:底层采用数组实现,用来存储队列的所有元素;

maxSize:数组最大容量;

first:队头索引属性;

size:队列有效元素的个数;

1,2,3,4,5

2、算法

这里采用最大容量为5的队列来说明,即maxSize设为5。

(1) 第一次使用队列时,依次添加5个元素:1,2,3,4,5,first指向1,size 大小为5,maxSize为5。

1,2,3,4,5

算法很简单:添加1时,各种为空、队列已满的判断条件暂时省掉;

add(int value) {

if (size == 0) {

first = 0;

}

elements[size++] = value;

}

(2) 调用2次pop()方法弹出获取队列元素,此时队列数据结构如下:

1,2,3,4,5

size为3,first指向3,maxSize始终为5。

pop() {

size--;

return elements[first++];

}

(3) 此时我们再向队列添加元素6、7,此时队列数据结构如下:

1,2,3,4,5

6,7,3,4,5

访问的顺序应该为:3, 4, 5, 6, 7,其中size为5,first指向3。此时步骤1、2的算法明显不支持数组的循环使用,我们需要利用取模来循环添加数据到数组,具体算法如下:

public class MyQueue {

    /**
* 底层数组
*/
private int[] elements; /**
* 队列最大容量
*/
private int maxSize; /**
* 队列头索引
*/
private int first; /**
* 队列有效元素的个数
*/
private int size; public MyQueue(int maxSize) {
this.maxSize = maxSize;
elements = new int[maxSize];
first = -1;
size = 0;
} /**
* 添加元素
*
* @param value
*/
public void add(int value) {
if (isFull()) {
throw new RuntimeException("队列已满。");
}
if (isEmpty()) {
first = 0;
}
// 队列未满但是(first + size >= maxSize)时,说明数组elements的first索引之后所有位置已填满,
// first索引之前有空位置可以插入元素, 新增元素插入位置算法为:(first + size) % maxSize。
if (first + size >= maxSize) {
elements[(first + size) % maxSize] = value;
} else {
elements[first + size] = value;
}
size++;
} /**
* 获取队列元素,只能取队列头,弹出式获取。
*
* @return
*/
public int pop() {
if (isEmpty()) {
throw new RuntimeException("队列为空。");
}
size--;
// first 索引指向maxSize - 1时,即first已到达数组最后的位置,则弹出之后需将first指向第1个元素,
// 实现数组循环使用
if (first == maxSize -1) {
int tmp = elements[first];
first = 0;
return tmp;
} else {
return elements[first++];
}
} /**
* 获取元素,不弹出
*
* @return
*/
public int peek() {
if (isEmpty()) {
throw new RuntimeException("队列为空。");
}
return elements[first];
} public boolean isFull() {
return size == maxSize;
} public boolean isEmpty() {
return size <= 0;
} public void display() {
if (isEmpty()) {
System.out.println("Queue is empty.");
return;
}
StringBuilder str = new StringBuilder();
for (int i = first; i < first + size; i++) {
if (i >= maxSize) {
str.append(elements[i % maxSize] + ", ");
} else {
str.append(elements[i] + ", ");
}
}
System.out.println(str.substring(0, str.length() - 2));
} public int size() {
return size;
}
}

Java - 可循环队列的更多相关文章

  1. atitit. java queue 队列体系and自定义基于数据库的队列总结o7t

    atitit. java queue 队列体系and自定义基于数据库的队列总结o7t 1. 阻塞队列和非阻塞队列 1 2. java.util.Queue接口, 1 3. ConcurrentLink ...

  2. lesson2:java阻塞队列的demo及源码分析

    本文向大家展示了java阻塞队列的使用场景.源码分析及特定场景下的使用方式.java的阻塞队列是jdk1.5之后在并发包中提供的一组队列,主要的使用场景是在需要使用生产者消费者模式时,用户不必再通过多 ...

  3. Java消息队列-Spring整合ActiveMq

    1.概述 首先和大家一起回顾一下Java 消息服务,在我之前的博客<Java消息队列-JMS概述>中,我为大家分析了: 消息服务:一个中间件,用于解决两个活多个程序之间的耦合,底层由Jav ...

  4. java 数据结构 队列的实现

    java 数据结构队列的代码实现,可以简单的进行入队列和出队列的操作 /** * java数据结构之队列的实现 * 2016/4/27 **/ package cn.Link; import java ...

  5. MinerQueue.java 访问队列

    MinerQueue.java 访问队列 package com.iteye.injavawetrust.miner; import java.util.HashSet; import java.ut ...

  6. Java操作队列

    Java操作队列 常见的几种模式:   1 简单队列simple 模型:(p + 队列 + c) P:生产者producer,将消息发送到队列 红色:消息队列 C:消费者consumer,从队列消费消 ...

  7. 数据结构与算法Java描述 队列

    package com.cjm.queue; /** * 数据结构与算法Java实现 队列 * * @author 小明 * */ public class Myqueue { private Nod ...

  8. 细说并发5:Java 阻塞队列源码分析(下)

    上一篇 细说并发4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文 ...

  9. Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例

    Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...

随机推荐

  1. CSS中为什么有的元素能够设置高度,而有的元素却不能设置高度与宽度?

    可以使用{display:block}将内联元素变为块级元素,同时使用{display:inline}将块级元素变为内联元素. {display:inline-block}又是怎么回事,根据张鑫旭老师 ...

  2. java.sql.SQLException: Could not retrieve transaction read-only status from server 问题解决

    网上有2种主要说法 第一种 问题描述: java代码在开始事务后,先做了一个查询,再insert,此时会报:          java.sql.SQLException: could not ret ...

  3. haproxy实现ssl套接字加密

    概述 如果你的应用使用SSL证书,则需要决定如何在负载均衡器上使用它们. 单服务器的简单配置通常是考虑客户端SSL连接如何被接收请求的服务器解码.由于负载均衡器处在客户端和更多服务器之间,SSL连接解 ...

  4. TypeError: this.setDynamic is not a function

    启动项目npm run serve 报错 Module build failed (from ./node_modules/_babel-loader@8.0.6@babel-loader/lib/i ...

  5. Atmel芯片使用

    ATMEL系列芯片 9X35 9G35可pin-to-pin替代9G10,具体需核对.此外即使pin-to-pin替代,外部应用也不一样. A5D2处理器,可支持linux/andriod. M7(M ...

  6. oracle下关于table的常用sql整理

    创建表,create TABLE table( 列名称1 数据类型1, 列名称2 数据类型2, 列名称3 数据类型3, ......); eg: create table TABLE_24751( i ...

  7. 十五,K8S集群调度原理及调度策略

    目录 k8s调度器Scheduler Scheduler工作原理 请求及Scheduler调度步骤: k8s的调用工作方式 常用预选策略 常用优先函数 节点亲和性调度 节点硬亲和性 节点软亲和性 Po ...

  8. 在values中添加colors.xml

    如何在values中添加colors.xml文件?按钮上的文字,背景色的动态变化的xml放在res/drawable里,现在我就说静态的xml文件吧. res/values/colors.xml< ...

  9. Selenium(4)

    练习1:使用selenium+firefox测试ecshop登录过程 一.WebDriver 1.启动浏览器 (1)启动Firefox浏览器 a.启动默认路径下的浏览器 WebDriver drive ...

  10. slplunk原始数据和索引数据大小比较

    DB目录总大小:2468MB 所有buckets的meta信息在.bucketManifest文件里: id,path,"raw_size","event_count&q ...