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

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

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. kali安装dnsdict6

    https://src.fedoraproject.org/lookaside/pkgs/thc-ipv6/thc-ipv6-2.7.tar.gz/2975dd54be35b68c140eb2a6b8 ...

  2. centos7安装nginx服务

    Nginx发音引擎x是一个免费的开源高性能HTTP和反向代理服务器,负责处理互联网上一些最大的网站的负载. 本教程将教你如何在你的CentOS Linux 7.5机器上安装和管理Nginx. 安装Ng ...

  3. Java对象的序列化和反序列化介绍

    一.什么序列化和反序列化以及作用: java序列化是指把java对象转换为字节序列的过程,而java反序列化是指把字节序列恢复为java对象的过程 1.序列化: 1)对象序列化的最主要的用处就是在传递 ...

  4. js中——限制文本框输入非数字

      //先把非数字的都替换掉,除了数字和.和/             obj.value = obj.value.replace(/[^\-\d./]/g, ""); //必须保 ...

  5. go语言入门(5)工程管理

    在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系,早期Go语言使用makefile作为工程管理的临时方案,后来的Go命令行工具的革命性之处在于彻底消除了工程文件的概念,完全用目录结 ...

  6. Bootstrap常用的自带插件

    Bootstrap自带的那些常用插件. 模态框 模态框的HTML代码放置的位置 务必将模态框的HTML代码放在文档的最高层级内(也就是说,尽量作为 body 标签的直接子元素),以避免其他组件影响模态 ...

  7. fragment初步认识

  8. 第六章 组件 58 组件切换-使用v-if和v-else结合flag进行切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  9. cmake 出现undefined reference to xxx 解决办法

    cmake没怎么用,主要觉得Clion很好用,但是默认clion使用的是cmake.再说一句clion是linux平台上很好用,个人强推. 当你使用clion的时候,如果使用了thread cstl等 ...

  10. stm32 cubemx hal dma uart参考例程,发送和接收

    参考:https://blog.csdn.net/toopoo/article/details/80012317https://blog.csdn.net/morixinguan/article/de ...