什么是队列呢?其实队列跟栈很像,我们可以把栈的底部给弄开,这样数据就可以从下面漏出来了,我们就从下面拿就好了。

  可以看到队列是新进先出,就跟我们显示生活中的排队一样,买火车票,飞机票等一样,先去的肯定是先上车;但是数据在出来的时候,难道我们要把上面所有的数据都往下移动一个位置吗?我们知道假如一个队列非常大,里面的数据量很多的时候我们这种要把所有的数据都移动一个位置这种行为是很坑爹的,于是我们想着用两个指针来表示这个队列中的所有数据,在这两个指针之外的数据,我们就当做什么也没看到;

  画个简单的图,由此可见队列中的指针是会随着数据的变化移动的,所以我们可以知道队列中的数据的索引可能不是从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(队列和优先级队列)的更多相关文章

  1. 《Java数据结构与算法》笔记-CH4-6优先级队列

    /** * 优先级队列 * 效率:插入O(n),删除O(1).第12章介绍如何通过堆来改进insert时间 */ class PriorityQueue { private int maxSize; ...

  2. Java数据结构和算法(五):队列

    简介 队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为 ...

  3. Java数据结构和算法(1)之队列

    1.队列的基本概念 队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插 ...

  4. 【python cookbook】【数据结构与算法】5.实现优先级队列

    问题:要实现一个队列,它能够以给定的优先级对元素排序,且每次pop操作时都会返回优先级最高的那个元素: 解决方案:采用heapq模块实现一个简单的优先级队列 # example.py # # Exam ...

  5. 《Java数据结构与算法》笔记-CH4-4循环队列

    /** * 循环队列 */ class Queue { private int maxSize; private long[] queue; private int front; private in ...

  6. java数据结构与算法值优先级队列

    一.优先级队列 什么是优先级队列:优先级队列是一种比栈和队列更加常用的一种数据结构.在优先级队列中,数据项按照关键字的值有序.数据项插入到队列中时,会按照顺序插入到合适的位置,用来保证队列的顺序. 生 ...

  7. Java数据结构和算法(五)——队列

    前面一篇博客我们讲解了并不像数组一样完全作为存储数据功能,而是作为构思算法的辅助工具的数据结构——栈,本篇博客我们介绍另外一个这样的工具——队列.栈是后进先出,而队列刚好相反,是先进先出. 1.队列的 ...

  8. Java数据结构和算法 - 栈和队列

    Q: 栈.队列与数组的区别? A: 本篇主要涉及三种数据存储类型:栈.队列和优先级队列,它与数组主要有如下三个区别: A: (一)程序员工具 数组和其他的结构(栈.队列.链表.树等等)都适用于数据库应 ...

  9. Java数据结构和算法(五)——队列

    队列.queue,就是现实生活中的排队. 1.简单队列: public class Queqe { private int array[]; private int front; private in ...

随机推荐

  1. 基于指纹考勤机的真实的PHP操作Access数据库成功案例(最终实现) 2011-11-2v

    听了我的建议,我们单位的食堂准备使用一台指纹考勤机统计吃饭人次,这样院里好给食堂的承包人以相应饭补.以前买过一台彩屏指纹机,数据库是access的,今儿又买了一台准备放到食堂里,而且考虑到停电,还特地 ...

  2. ffmpeg重要的参考学习网址

    http://lib.csdn.net/liveplay/knowledge/1586 FFmpeg滤镜使用指南 http://blog.csdn.net/fireroll/article/detai ...

  3. 1.ehcache实现页面整体缓存和页面局部缓存

    转自:https://www.cnblogs.com/jianjianyang/p/4933016.html 好长时间没写博客了,真的是没时间啊.ps:其实就是懒!!接下来几篇要写下缓存,这里主要写下 ...

  4. [X264] MinGW编译x264,VC中调用libx264.dll-------------<参考转>

    1. 下载并按照MinGW,最好就缺省按照    http://sourceforge.net/projects/ ... ler/mingw-get-inst/    把C:\MinGW\bin添加 ...

  5. 对avalon的类名操作进行升级

    在对SVG元素进行类名操作时,发现有一个坑爹的事情,它的className竟然是一个对象,因此报一系列BUG.第一次想到的方法是添加setClasses, getClasses两个更底层的方法.于是相 ...

  6. Information Retrieval

    [Information Retrieval] 1.信息检索/获取(Information Retrieval,简称IR) 是从大规模非结构化数据(通常是文本)的集合(通常保存在计算机上)中找出满足用 ...

  7. react-navigation 3.x版本的push、navigate、goback、pop、dispatch等常用方法

    一.方法简介 1. 应用中的每个页面组件都会自动提供 this.props.navigation this.props.navigation可以获取的一些方法: navigate - 转到另一个页面, ...

  8. Draw Call(Unity 5中显示为SetPass calls

    Draw Call(Unity 5中显示为SetPass calls

  9. 除了DFS的空间恒定为宽度*深度之外,其余都是宽度^深度次方

  10. Zookeeper 目录

    Zookeeper 目录 Zookeeper 致力于提供一个高性能.高可用,且具有严格的顺序访问控制能力(主要是写操作的严格顺序性)的分布式协调服务.以下是我整理的笔记. 一.分布式理论基础 1.1 ...