java数据结构与算法:单向队列与环形队列详解(图片+代码)
Posted 温文艾尔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java数据结构与算法:单向队列与环形队列详解(图片+代码)相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、队列介绍
- 队列是一个有序列表,可以用数组或是链表来实现
- 遵循先入先出的原则。即:先存入队列的数据,要先取出,后存入的要后取出。
二、单向队列数组模拟队列
- 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中maxSize是该队列的最大容量
- 因为队列的输出,输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变
1.单向队列模拟图
当我们将数据存入队列时称为“addQueue”,addQueue的处理需要有两个步骤
- 将尾指针向后移动:rear+1,当front == rear,则队列为空
- 若尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所指的数组元素中,当rear == maxSize-1时队列为满
注意
- front指向的是队列头的前一个位置
- rear指向的是队列最后一个数据
单项队列代码模拟
package org.wql.Queue;
/**
* Description
* User:
* Date:
* Time:
*/
public class QueueTest01 {
public static void main(String[] args) {
ArrayQueue arrayQueue = new ArrayQueue(3);
arrayQueue.addData(1);
arrayQueue.addData(2);
arrayQueue.addData(3);
arrayQueue.showData();
int data = arrayQueue.getData();
System.out.println("取出数据1");
arrayQueue.showData();
arrayQueue.addData(4);
System.out.println("增加数据4");
arrayQueue.showData();
//展示头部
int head = arrayQueue.gethead();
System.out.println("头部数据是:"+head);
}
}
class ArrayQueue{
private int maxSize;
private int rear;
private int front;
private int[] arr;
//初始化队列
public ArrayQueue(int MaxSize){
maxSize=MaxSize;
arr = new int[maxSize];
rear=-1;
front=-1;
}
//判断队列是否已满
public boolean isFull(){
return rear==maxSize-1;
}
//判断队列是否为空
public boolean isEmpty(){
return rear==front;
}
//添加数据到队列
public void addData(int data){
//在队列未满的状态下才可添加数据
if (!isFull()){
arr[++rear]=data;
}else {
System.out.println("队列已满,不能加入数据");
return;
}
}
//从队列中取数据
public int getData(){
//在队列非空的状态下才可取得数据
if(!isEmpty()){
return arr[++front];
}else {
throw new RuntimeException("队列为空,不能取数据");
}
}
//显示队列中的所有数据
public void showData(){
if(!isEmpty()){
for(int i=front+1;i<rear+1;i++){
System.out.println(arr[i]);
}
}else{
System.out.println("队列没有数据");
}
}
//显示队列的头数据(只是显示,并不取出)
public int gethead(){
if(isEmpty()) {
throw new RuntimeException("队列为空,没有数据");
}
return arr[front+1];
}
}
此时我们发现单项队列存在的缺陷,一旦队列满,则无法再添加数据,曾经数据占用的位置依然被占用,故需要使用环形队列
三、环形队列数组模拟队列
思路如下
- front变量的含义做一个调整:front就指向队列的第一个元素,而不是像单项队列一样指向第一个元素的前一个位置,arr[front]就是队列的第一个元素,front初始值为0
- rear变量的含义也做一个调整:rear指向队列的最后一个元素的后一个位置,这样可区分环形队列的队满与队空,rear的初始值为0
- 当队列满时,条件是(rear+1)%maxSize=front
- 队列为空的条件是rear==front
- 队列中有效的数据个数为(rear+maxSize-front)%maxSize
环形数列需要牺牲一个位置作为约定
我们可以通过画图来说明问题
设maxSize为4,当队列满时有此场景
front代表队列第一个元素的位置,front=0,rear代表最后一个元素的后一个位置,rear=3
故此时(rear+1)%maxSize=front,因为我们牺牲了一个位置作为约定,故队列中的数据有效个数为(3+4-0)%4=3
环形队列代码模拟
package org.wql.Queue;
/**
* Description
* User:
* Date:
* Time:
*/
public class CircleQueueTest02 {
public static void main(String[] args) {
CircleArrayQueue circleArrayQueue = new CircleArrayQueue(4);
System.out.println("添加数据");
circleArrayQueue.addData(1);
circleArrayQueue.addData(2);
circleArrayQueue.addData(3);
circleArrayQueue.showData();
// f=0,r=3
int data = circleArrayQueue.getData();
System.out.println("取出数据:"+data);
circleArrayQueue.showData();
// f=1,r=3
circleArrayQueue.addData(4);
System.out.println("增加数据:4");
// f=1,r=0
circleArrayQueue.showData();
int head = circleArrayQueue.gethead();
System.out.println("第一个元素为:"+head);
int size = circleArrayQueue.getQueueSize();
System.out.println("环形队列中的有效元素个数:"+size);
}
}
class CircleArrayQueue{
private int maxSize;
private int rear;
private int front;
private int[] arr;
//初始化队列
public CircleArrayQueue(int MaxSize){
maxSize=MaxSize;
arr = new int[maxSize];
}
//判断队列是否已满
public boolean isFull(){
return (rear+1)%maxSize==front;
}
//判断队列是否为空
public boolean isEmpty(){
return rear==front;
}
//添加数据到队列
public void addData(int data){
//在队列未满的状态下才可添加数据
if (!isFull()){
arr[rear]=data;
rear=(rear+1)%maxSize;
}else {
System.out.println("队列已满,不能加入数据");
return;
}
}
//从队列中取数据
public int getData(){
//在队列非空的状态下才可取得数据
if(!isEmpty()){
front=(front+1)%maxSize;
return arr[front-1];
}else {
throw new RuntimeException("队列为空,不能取数据");
}
}
//显示队列中的所有数据
public void showData(){
if(!isEmpty()){
for(int i=front;i<front+getQueueSize();i++){
System.out.println(arr[i]);
}
}else{
System.out.println("队列没有数据");
}
}
//显示队列的头数据(只是显示,并不取出)
public int gethead(){
if(isEmpty()) {
throw new RuntimeException("队列为空,没有数据");
}
return arr[front];
}
//显示当前队列中元素的有效个数
public int getQueueSize(){
return (rear+maxSize-front)%maxSize;
}
}
以上是关于java数据结构与算法:单向队列与环形队列详解(图片+代码)的主要内容,如果未能解决你的问题,请参考以下文章