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

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

  画个简单的图,由此可见队列中的指针是会随着数据的变化移动的,所以我们可以知道队列中的数据的索引可能不是从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. Java进行spark计算

    首先在Linux环境安装spark: 可以从如下地址下载最新版本的spark: https://spark.apache.org/downloads.html 这个下载下来后是个tgz的压缩包,解压后 ...

  2. 学习blus老师js(5)--DOM操作应用高级

    一.表格应用 - 1 获取 tBodies.tHead.tFoot.rows.cells 一个表格可以有很多tbody,所以tBodies是数组: 一个表格只能有一个thead和tfoot,所以tHe ...

  3. poj 2377 Bad Cowtractors (最大生成树prim)

    Bad Cowtractors Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) To ...

  4. Oracle NVL与NVL2函数

    nvl( ) 函数 从两个表达式返回一个非 null 值. 语法 NVL(eExpression1, eExpression2) 参数 eExpression1, eExpression2 如果 eE ...

  5. 使用Javamail发送邮件Util

    maven: <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artif ...

  6. react之引用echarts

    react之引用echarts npm: npm install echarts --save 代码: import React, { Component } from 'react'; // 引入 ...

  7. Spring Boot SSO单点登入

    https://github.com/ITDragonBlog/daydayup/tree/master/SpringBoot-SSO 流程图: 1: Redis 保存用户信息 到Redis(KEY- ...

  8. Remove “Quick Access” entry in Eclipse Juno

    Here is a quick hack which doesn't require any plugin installation, instead you just need to add a f ...

  9. Oracle安装盘空间不足,对.DBF文件进行迁移

    一. select * from dba_data_files 使用该条语句可以查看当前库中有多少表空间并且DBF文件的存储位置 二. 找到对应的dbf文件,将该文件复制到你需要移动的位置 三. 开始 ...

  10. ORACLE BI Publisher Enterprise

    二.带参数 BEGIN:{$FIRST_DAY_OF_MONTH()$} END:{$SYSDATE()$} 三\加下拉菜单值