java数据结构和算法03(队列和优先级队列)
什么是队列呢?其实队列跟栈很像,我们可以把栈的底部给弄开,这样数据就可以从下面漏出来了,我们就从下面拿就好了。

可以看到队列是新进先出,就跟我们显示生活中的排队一样,买火车票,飞机票等一样,先去的肯定是先上车;但是数据在出来的时候,难道我们要把上面所有的数据都往下移动一个位置吗?我们知道假如一个队列非常大,里面的数据量很多的时候我们这种要把所有的数据都移动一个位置这种行为是很坑爹的,于是我们想着用两个指针来表示这个队列中的所有数据,在这两个指针之外的数据,我们就当做什么也没看到;
画个简单的图,由此可见队列中的指针是会随着数据的变化移动的,所以我们可以知道队列中的数据的索引可能不是从0开始的,这点和栈有很大的不同(注意,索引的话最下面最小为0,最上面最大为队列最大值减一)

这里我们考虑一下,假如尾指针不断的向上移动到队列最尾部了,这个时候还要添加数据会怎么样?其实很简单,可以在头指针的下面(前提是经过删除操作,头指针下面有位置)的地方赋值,并且把尾指针指过来,我们把上面这个图进行改造一下:

1.队列的简单实现:
这种方式就叫做循环队列,或者叫缓冲环,下面我们也基于数组的形式用代码来简单实现这种队列的方式;
package com.wyq.thread;
import java.util.Arrays;
public class MyQueue {
private Object[] arr;
//队列最大数量
private int maxlength;
//队列头指针
private int before;
//队列尾指针
private int after;
//队列中实际数据的个数
private int size;
public MyQueue(){
this(5);
}
public MyQueue(int len){
arr = new Object[len];
this.maxlength = len;
before = 0;//刚开始头指针指向队列最下面的位置
after = -1;//尾指针等于-1,相当于此时尾指针没有指向任何位置,等到有数据之后尾指针就会向上移动
size = 0;//刚开始一个数据都没有
}
//判断当前队列中数据是不是满的
public boolean isFull(){
return (maxlength==size);
}
//向队列中增加数据
public int add(Object obj){
//假如队列已经满了,就抛出异常
if (isFull()) {
try {
throw new Exception("不好意思队列满了,请删除一些东西再说!");
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}else{
//队列中数据没有满的话,判断此时尾指针是不是指向最上面,是的话首先将尾指针指向最下面
if (after==maxlength-1) {
after = -1;
}
//尾指针向上移动一个位置,并且放入数据
arr[++after] = obj;
//由于增加了数据,所以队列中的实际数据的数量增加
size++;
return 1;
}
}
//删除数据
public int delete(){
//如果队列不是一个空队列,那么我们就删除头指针指向的数据,其实就是将这个数据变为null,然后头指针向上移动
if (size>0) {
arr[before++]=null;
//这里进行判断假如头指针移动到最顶端,那么就把头指针重新移动到索引为0的位置
if (before==maxlength) {
before=0;
}
//删除了数据,那么队列中的实际数量减少
size--;
return 1;
}
return 0;
}
//查看头指针指向的数据
public Object peek(){
return arr[before];
}
//队列中数据的实际数量
public int size(){
return size;
}
//展示队列中的所有数据
public void display(){
System.out.println(Arrays.toString(arr));
}
public static void main(String[] args) {
MyQueue myQueue = new MyQueue();
for (int i = 0; i < 5; i++) {
myQueue.add(i);
}
myQueue.delete();
myQueue.delete();
myQueue.display();
myQueue.add(100);
myQueue.display();
System.out.println(myQueue.peek());
System.out.println("队列中数据的数量:"+myQueue.size());
}
}

2.优先级队列
什么又是优先级队列呢?你看,虽然我们上面实现的队列基本的功能是可以使用的,但是插入的数据是没有顺序的,比如我插入的顺序是3,5,1,4,,在队列中是顺序就是3514,但是假如是优先级队列的话,在往队列中插入数据的时候会进行一个排序,就会变成5431这样的顺序;
那可能会有人想问这有什么用啊?例如在抢先式多任务操作系统中程序就是排列在优先级队列中,这样优先级最高的队列就会优先执行。
我还是简单的画一个图;

我们就用一个Integert数组实现一下这个原理,很明显插入数据是比较麻烦的,我们重点应该是add方法;
package com.wyq.thread;
import java.util.Arrays;
public class MyPriorityQueue {
//由于删除的时候需要将要删除的位置赋值为null,所以就用Integer[]数组了
private Integer[] priorityArr;
//优先级队列最大数量
private int maxlength;
//优先级队列中实际数据的个数
private int size;
public MyPriorityQueue(){
this(5);
}
public MyPriorityQueue(int len){
priorityArr = new Integer[len];
this.maxlength = len;
size = 0;//刚开始一个数据都没有
}
//判断当前队列中数据是不是满的
public boolean isFull(){
return (maxlength==size);
}
//向队列中增加数据,数据从上到下依次增大
public int add(int value){
int i;
//假如队列中一个数据都没有,那就将数据添加到第一个位置
if (size==0) {
priorityArr[size++] = value;
return 1;
}else{
//如果队列中数据已经满了,那就抛出异常
if (size==maxlength) {
try {
throw new Exception("优先级队列满了,还存,存你妹啊!");
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
//此处可以说是这个方法的核心,先用指针i指向队列的最上面,将我们要添加的数据和最上面的那个数据进行比较,比它大的话就将顶端数据向上移动一个位置
//然后将指针i向下移动一个位置,此时由于在while循环中,就会继续将要插入的数据和i指向的数据进行比较,重复这个步骤,直到要插入的数据比指针指向
//的数据要小,就将数据插入这个数的上面,即最后的位置即是i+1
i = size-1;
while(i>=0 && value > priorityArr[i]) {
priorityArr[i+1] = priorityArr[i];
i--;
}
priorityArr[i+1]=value;
size++;
return 1;
}
}
//删除数据,由于数据从上到下依次增大,我们可以按照从小到大删除或者从大到小删除
//我们这里就实现从大到小删除,只需在这个方法中设置一个指向最上面的指针即可;
//假如要实现从小到大删除,则需要设置一个类变量为最下面的头指针
public int delete(){
int after = size-1;
int value = priorityArr[after];
priorityArr[after]=null;
size--;
return value;
}
//查看头指针指向的数据
public int peekMin(){
return priorityArr[size-1];
}
//队列中数据的实际数量
public int size(){
return size;
}
//展示队列中的所有数据
public void display(){
System.out.println(Arrays.toString(priorityArr));
}
public static void main(String[] args) {
MyPriorityQueue priority = new MyPriorityQueue();
priority.add(3);
priority.add(10);
priority.add(8);
priority.add(1);
priority.add(100);
priority.display();
priority.delete();
priority.delete();
priority.display();
System.out.println("队列中最小的元素为:"+priority.peekMin());
System.out.println("队列中实际的数据的个数为:"+priority.size());
}
}

其实在这里我们也可以看到int数组和Integer数组的区别,最大的区别就是可不可以用null,在delete方法中,假如我们用的是int[]数组,那删除的位置我们用什么表示呢?用0?还是-1?假如用0表示,那我们在用队列的时候插入数据0,那么,此时队列中的0就有两种意思,一种是没有数据,一种是数据0,于是用Integer就没有这个烦恼
java数据结构和算法03(队列和优先级队列)的更多相关文章
- 《Java数据结构与算法》笔记-CH4-6优先级队列
/** * 优先级队列 * 效率:插入O(n),删除O(1).第12章介绍如何通过堆来改进insert时间 */ class PriorityQueue { private int maxSize; ...
- Java数据结构和算法(五):队列
简介 队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为 ...
- Java数据结构和算法(1)之队列
1.队列的基本概念 队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插 ...
- 【python cookbook】【数据结构与算法】5.实现优先级队列
问题:要实现一个队列,它能够以给定的优先级对元素排序,且每次pop操作时都会返回优先级最高的那个元素: 解决方案:采用heapq模块实现一个简单的优先级队列 # example.py # # Exam ...
- 《Java数据结构与算法》笔记-CH4-4循环队列
/** * 循环队列 */ class Queue { private int maxSize; private long[] queue; private int front; private in ...
- java数据结构与算法值优先级队列
一.优先级队列 什么是优先级队列:优先级队列是一种比栈和队列更加常用的一种数据结构.在优先级队列中,数据项按照关键字的值有序.数据项插入到队列中时,会按照顺序插入到合适的位置,用来保证队列的顺序. 生 ...
- Java数据结构和算法(五)——队列
前面一篇博客我们讲解了并不像数组一样完全作为存储数据功能,而是作为构思算法的辅助工具的数据结构——栈,本篇博客我们介绍另外一个这样的工具——队列.栈是后进先出,而队列刚好相反,是先进先出. 1.队列的 ...
- Java数据结构和算法 - 栈和队列
Q: 栈.队列与数组的区别? A: 本篇主要涉及三种数据存储类型:栈.队列和优先级队列,它与数组主要有如下三个区别: A: (一)程序员工具 数组和其他的结构(栈.队列.链表.树等等)都适用于数据库应 ...
- Java数据结构和算法(五)——队列
队列.queue,就是现实生活中的排队. 1.简单队列: public class Queqe { private int array[]; private int front; private in ...
随机推荐
- 转转转-精通js正则表达式
原文地址:http://www.cnblogs.com/aaronjs/archive/2012/06/30/2570970.html 正则表达式可以: •测试字符串的某个模式.例如,可以对一个输入字 ...
- Bootstrap-CL:多媒体对象
ylbtech-Bootstrap-CL:多媒体对象 1.返回顶部 1. Bootstrap 多媒体对象(Media Object) 本章我们将讲解 Bootstrap 中的多媒体对象(Media O ...
- jQuery layer弹出层插件 http://layer.layui.com/直接上官网学
在许多网站中,经常用到弹出层,有时候为了达到更好的用户体验,你将写繁琐的css跟js,这款 jquery-layer可以让你想到即可做到的web弹窗/层js组件.layer侧重于用户灵活的自定义,为不 ...
- Lucene根据字段进行自定义搜索扩展
最近需要对公司的产品搜索功能做一步改动,搜索到的结果首先按照是否有库存进行排序,然后再按照销量.由于库存量也是一个整数,如果直接按照库存量进行倒序排序的话,是不符合要求的,Lucene也没有支持我们这 ...
- Spring batch学习 详细配置解读(3)
第一篇讲到普通job 配置 那么spring batch 给我们提供了丰富的配置,包括定时任务,校验,复合监听器,父类,重启机制等. 下面看一个动态设置读取文件的配置 1.动态文件读取 <?x ...
- selenium+python自动化81-html报告优化(饼图+失败重跑+兼容python2&3)
优化html报告 为了满足小伙伴的各种变态需求,为了装逼提升逼格,为了让报告更加高大上,测试报告做了以下优化: 测试报告中文显示,优化一些断言失败正文乱码问题 新增错误和失败截图,展示到html报告里 ...
- centos7.3部署django用uwsgi和nginx[亲测可用]
现在nginx nginx version: nginx/1.10.2 uwsgi 2.0.17 django2.0.5 都已经完成完毕,那么开始 uwsgi 配置 uwsgi支持ini.xml等多种 ...
- ES6系列_6之新增的数组知识
1.JSON数组格式转换 JSON的数组格式就是为了前端快速的把JSON转换成数组的一种格式,json数组格式如下: let json = { '0': '男', '1': '女', length:3 ...
- eclipse Android 开发基础 Activity 窗体 界面
eclipse Android 开发基础 新建工程 新建布局layout,new Android Activity就相当于窗体Form. 新建Activity自动生成src下同名的java代码. pu ...
- FireDAC 汉字字段名称过滤
[FireDAC][Stan][Eval]-107. Invalid character found [ 拼音码 like '%A%' ] 英文字段名称过滤正常 汉字字段名过滤报错. 莫非不支持汉字字 ...