在某些时候,我们不能被要求像数组一样可以使用索引随机访问,而是需要被限制顺序处理业务,今天介绍一种先进先出(FIFO)的线性数据结构:队列,

当然,还有后进先出(LIFO)的处理方式,即为栈(后续有时间再另说)。

先进先出的数据结构:(以下图片非原创,来自网络)

在 FIFO 数据结构中,将首先处理添加到队列中的第一个元素

如上图所示,队列是典型的 FIFO 数据结构。插入(insert)操作也称作入队(enqueue),新元素始终被添加在队列的末尾。 删除(delete)操作也被称为出队(dequeue)。 你只能移除第一个元素

低效的队列实现:(此小段内容非原创,来自网络)

为了实现队列,我们可以使用动态数组和指向队列头部的索引。

如上所述,队列应支持两种操作:入队和出队。入队会向队列追加一个新元素,而出队会删除第一个元素。 所以我们需要一个索引来指出起点。

这是一个供你参考的实现:

// "static void main" must be defined in a public class.

class MyQueue {
// store elements
private List<Integer> data;
// a pointer to indicate the start position
private int p_start;
public MyQueue() {
data = new ArrayList<Integer>();
p_start = 0;
}
/** Insert an element into the queue. Return true if the operation is successful. */
public boolean enQueue(int x) {
data.add(x);
return true;
};
/** Delete an element from the queue. Return true if the operation is successful. */
public boolean deQueue() {
  if (isEmpty() == true) {
  return false;
}
  p_start++;
  return true;
}
/** Get the front item from the queue. */
public int Front() {
return data.get(p_start);
}
/** Checks whether the queue is empty or not. */
public boolean isEmpty() {
return p_start >= data.size();
}
};

public class Main {
public static void main(String[] args) {
MyQueue q = new MyQueue();
q.enQueue(5);
q.enQueue(3);
if (q.isEmpty() == false) {
System.out.println(q.Front());
}
q.deQueue();
if (q.isEmpty() == false) {
System.out.println(q.Front());
}
q.deQueue();
if (q.isEmpty() == false) {
System.out.println(q.Front());
}
}
}

缺点


上面的实现很简单,但在某些情况下效率很低。 随着起始指针的移动,浪费了越来越多的空间。 当我们有空间限制时,这将是难以接受的。

让我们考虑一种情况,即我们只能分配一个最大长度为 5 的数组。当我们只添加少于 5 个元素时,我们的解决方案很有效。 例如,如果我们只调用入队函数四次后还想要将元素 10 入队,那么我们可以成功。

但是我们不能接受更多的入队请求,这是合理的,因为现在队列已经满了。但是如果我们将一个元素出队呢?


实际上,在这种情况下,我们应该能够再接受一个元素。

 循环队列的实现(原创)

上面我们提供了一种简单但低效的队列实现。

更有效的方法是使用循环队列。 具体来说,我们可以使用固定大小的数组两个指针来指示起始位置(head)和结束位置(tail)。 目的是重用我们之前提到的被浪费的存储

循环队列的实现最为关键是要用检测队列空(empty)与满(full)的策略,以下附上原码和输出结果。

1、抽象了一个队列的简单接口(ICircleQueue)

package com.chengcai.util;
/**
 * Created by chengcai on 2019/3/7.
 */
public interface ICircleQueue<E> {
    boolean enQueue(E e);
    E deQueue();
    boolean isFull();
    boolean isEmpty();
    CircleQueueEntity getQueueEntity();
    int getQueueItemSize();
    int getRequestElementIndex();
}
2.抽像类(AbstractComDataSet),暂作了定义队列长度,留个扩展
public abstract class AbstractComDataSet {
    static int QueueBufferSize=10;
} 3.队列属性类(CircleQueueEntity)
package com.chengcai.util;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by chengcai on 2019/3/7.
 */
public class CircleQueueEntity<T> {
    private int head;
    private int tail;
    private int index;
    private int size;
    private List<T> list = null;
    private List<T> deList=null;     public CircleQueueEntity() {
        head = 0;
        tail = 0;
        index = 0;
        size = AbstractComDataSet.QueueBufferSize;
        ConstructList();
    }
    void ConstructList()
    {
        list=new ArrayList<T>();
        deList=new ArrayList<T>();
        for (int i=0;i< size;i++)
        {
            list.add(null);
        }
    }
    public  void setHead(int pointer)
    {
        this.head=pointer;
    }
    public int getHead()
    {
        return this.head;
    }
    public void setTail(int pointer)
    {
        this.tail=pointer;
    }
    public int getTail()
    {
        return this.tail;
    }
    public void setIndex(int pointer)
    {
        this.index= pointer;
    }
    public int getIndex()
    {
        return this.index;
    }
    public int getSizeOnly()
    {
        return size;
    }
    public List<T> getListCollection()
    {
        return this.list;
    }
    public List<T> getDeListCollection(){ return this.deList;}
}
4.循环队列类(CircleQueue)
package com.chengcai.util;
import java.util.Iterator;
import java.util.List; /**
 * Created by chengcai on 2019/3/7.
 */
public class CircleQueue<E> implements ICircleQueue<E>{
    private CircleQueueEntity<E> entity=null;
    private  int requestElementIndex=0;
    public CircleQueue()
    {
        entity=new CircleQueueEntity<E>();
    }     @Override
    public boolean enQueue(E e)
    {
        if (isFull())
            return false;
        int index=entity.getIndex();
        int tail=entity.getTail();
        int size=entity.getSizeOnly();
        if (tail>=size) {
            entity.setTail(0);
            tail=entity.getTail();
            entity.setIndex(0);
            index=entity.getIndex();
        }
        entity.getListCollection().set(entity.getTail(),e);
        entity.setIndex(index + 1);
        entity.setTail(tail + 1);
        this.requestElementIndex++;
        return true;
    }
    @Override
    public E deQueue()
    {
        if (isEmpty())
            return null;
        int head =entity.getHead();
        int size=entity.getSizeOnly();
        E deQueueElement=entity.getListCollection().get(head);
        entity.getDeListCollection().add(deQueueElement);
        entity.getListCollection().set(head,null);
        entity.setHead(head+1);
        head=entity.getHead();
        if (head>size-1)
        {
            entity.setHead(0);
        }
        return  deQueueElement;
    }     @Override
    public boolean isFull()
    {
        List<E> list=entity.getListCollection();
        for(E obj:list)
        {
            if (obj==null)
                return false;
        }
        return true;
    }     @Override
    public boolean isEmpty()
    {
        List<E> list=entity.getListCollection();
        boolean isnull=true;
        for (E obj:list) {
            if (obj!=null)
                return false;
        }
        return isnull;
    }     @Override
    public  CircleQueueEntity getQueueEntity()
    {
        return entity;
    }
    @Override
    public int getQueueItemSize(){
        return entity.getListCollection().size();
    }     @Override
    public int getRequestElementIndex()
    {
        return this.requestElementIndex;
    }
    public  int getQueueElementCount()
    {
        int count=0;
        Iterator it =entity.getListCollection().iterator();
        while (it.hasNext())
        {
            if (it.next()!=null)
                count++;
        }
        return count;
    }
}

5.Main 
package com.chengcai;
import com.chengcai.util.*;
public class Main {     private static String enQueue(ICircleQueue q, int[] data)
    {
        StringBuilder sb =new StringBuilder();
        String strTemp="";
        boolean isSuccess =false;
        int requestElementIndex=q.getRequestElementIndex();         sb.append("已成功入队:");
        for (int i=requestElementIndex;i<data.length;i++)
        {
            isSuccess=q.enQueue(data[i]);
            if (isSuccess) {
                strTemp += Integer.toString(data[i]) + ",";
            }
        }
        sb.append(strTemp);
        return sb.toString();
    }     private  static String waitQueue(ICircleQueue q, int[] data)
    {
        StringBuilder sb =new StringBuilder();
        String strTemp="";
        int requestElementIndex=q.getRequestElementIndex();         strTemp="正在排队的元素:";
        for (int i=requestElementIndex;i<data.length;i++)
        {
            strTemp += Integer.toString(data[i]) + ",";
        }
        sb.append(strTemp);
        return  sb.toString();
    }     private static String deQueue(ICircleQueue q,int deQueueFlag)
    {
        StringBuilder sb =new StringBuilder();
        String strTemp="";         sb.append("已成功出队(FIFO):");
        for (int i=0;i<deQueueFlag;i++)
        {
            strTemp= strTemp + q.deQueue().toString();
            strTemp += ",";
        }
        sb.append(strTemp);
        return  sb.toString();
    }     public static void main(String[] args) {
        int[] data={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,20,21,22,23,24,25};
        ICircleQueue q=new CircleQueue();
        String strPrint;
        strPrint="当前队列长度为:"+q.getQueueItemSize();
        System.out.println(strPrint);
        strPrint=enQueue(q,data);
        System.out.println(strPrint);
        strPrint=waitQueue(q,data);
        System.out.println(strPrint);
        strPrint=deQueue(q,3);
        System.out.println(strPrint);
        strPrint=enQueue(q,data);
        System.out.println(strPrint);
        strPrint=waitQueue(q,data);
        System.out.println(strPrint);
        strPrint=deQueue(q,8);
        System.out.println(strPrint);
        strPrint=enQueue(q,data);
        System.out.println(strPrint);
        strPrint=waitQueue(q,data)+"全部元素已入队列";
        System.out.println(strPrint);
    }
}
 
6.运行结果:
 
当前队列长度为:10
已成功入队:1,2,3,4,5,6,7,8,9,10,
正在排队的元素:11,12,13,14,15,20,21,22,23,24,25,
已成功出队(FIFO):1,2,3,
已成功入队:11,12,13,
正在排队的元素:14,15,20,21,22,23,24,25,
已成功出队(FIFO):4,5,6,7,8,9,10,11,
已成功入队:14,15,20,21,22,23,24,25,
正在排队的元素:全部元素已入队列
 

Java实现一个简单的循环队列的更多相关文章

  1. Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  2. 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小

    原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...

  3. 使用JAVA写一个简单的日历

    JAVA写一个简单的日历import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateF ...

  4. Java实现一个简单的文件上传案例

    Java实现一个简单的文件上传案例 实现流程: 1.客户端从硬盘读取文件数据到程序中 2.客户端输出流,写出文件到服务端 3.服务端输出流,读取文件数据到服务端中 4.输出流,写出文件数据到服务器硬盘 ...

  5. 使用 java 实现一个简单的 markdown 语法解析器

    1. 什么是 markdown Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的 ...

  6. java:jsp: 一个简单的自定义标签 tld

    java:jsp: 一个简单的自定义标签 tld 请注意,uri都是:http://www.tag.com/mytag,保持统一,要不然报错,不能访问 tld文件 <?xml version=& ...

  7. Java实现一个简单的网络爬虫

    Java实现一个简单的网络爬虫 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWri ...

  8. BAT面试题:使用数组实现一个简单的阻塞队列

    这道题是我亲身经历的一道大厂面试题,非常值得分享! 这道题可以分为两个步骤进行编码解答,第一步是基于数组实现一个队列,第二步是实现线程阻塞. 如果是基于数组实现栈的数据结构,那么我们只需要一个指针进行 ...

  9. Java写一个简单学生管理系统

    其实作为一名Java的程序猿,无论你是初学也好,大神也罢,学生管理系统一直都是一个非常好的例子,初学者主要是用数组.List等等来写出一个简易的学生管理系统,二.牛逼一点的大神则用数据库+swing来 ...

随机推荐

  1. JDK源码分析(8) StringBuffer & StringBuilder

    简介 StringBuffer与StringBuilder是两个常用的操作字符串的类.大家都知道,StringBuilder是线程不安全的,而StringBuffer是线程安全的.前者是JDK1.5加 ...

  2. [Treap][学习笔记]

    平衡树 平衡树就是一种可以在log的时间复杂度内完成数据的插入,删除,查找第k大,查询排名,查询前驱后继以及其他许多操作的数据结构. Treap treap是一种比较好写,常数比较小,可以实现平衡树基 ...

  3. PyCharm的安装和应用

    一.前言 大约几年以前,我曾经跟别人吹过牛逼,说我会深度学习.吹牛的后果就是我得逼自己把深度学习放在我的to-do-list里,在别人揭发我吹牛之前把深度学习学会了,才能名正言顺得对外宣称,我并没有吹 ...

  4. Jenkins_安装

    1.下载war包 wget -c -O ./jenkins.war http://mirrors.jenkins.io/war-stable/latest/jenkins.war 2.启动下载好的wa ...

  5. MySQL数据转移至SQL Server详解

    最近有个活是mysql数据转移到sql server 2012,直接手动转工作量太大,发现网上有工具教程,则记录一下. 一.安装MySQL ODBC驱动为MySQL安装Connector/ODBC驱动 ...

  6. http 400错误【原】

    http 400错误现象: 使用java代码访问某PDF文件地址, 报了http 400错误 ,浏览器却能正常访问 . 所以猜测浏览器对地址做了额外处理. 异常代码 String srcUrl = & ...

  7. 基于jdk1.8的ArrayList源码分析

    前言ArrayList作为一个常用的集合类,这次我们简单的根据源码来看看AarryList是如何使用的. ArrayList拥有的成员变量 public class ArrayList<E> ...

  8. 罗技M185鼠标飘

    不用鼠标垫会好很多,艹.今天买了个树脂鼠标垫解决问题.

  9. Linux学习之管道符、重定向、通配符、转义符、环境变量

    Linux学习之管道符.重定向.通配符.转义符.环境变量 1. 输入输出重定向 输入重定向是指把文件导入命令中. 输出重定向是指把原本要输出到屏幕的数据信息写入指定文件中. a 标准输入重定向(STD ...

  10. 熟悉activemq的初步试用

      1.在服务器(阿里云ubuntu16.04)上安装activemq,我是直接下载activemq: wget http://archive.apache.org/dist/activemq/apa ...