avatar

java实现循环队列

数据结构之队列

队列介绍

队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。

顺序队列

建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置,如图所示
每次在队尾插入一个元素是,rear增1;每次在队头删除一个元素时,front增1。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。当front=rear时,队列中没有任何元素,称为空队列。当rear增加到指向分配的连续空间之外时,队列无法再插入新元素,但这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。

循环队列

在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。除了一些简单应用之外,真正实用的队列是循环队列。

普通顺序队列

package com.csw.queue;

import java.util.Scanner;

/**
* @Auther: 行路
* @Date: Created on 2020/4/2 19:16 星期四
* @Description: com.csw.queue 使用数组模拟队列
* @version: 1.0
*/

public class ArrayQueueDemo {
public static void main(String[] args) {
//创建一个队列
ArrayQueue queue= new ArrayQueue(3);
char key=' ';//接收用户输入
Scanner scanner = new Scanner(System.in);
boolean loop=true;
//输出一个菜单
while(loop){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
key=scanner.next().charAt(0); //接收一个字符
switch (key){
case 's':
queue.showQueue();
break;

case 'a':
System.out.println("输入一个数字");
int value=scanner.nextInt();
queue.addQueue(value);
break;
case 'g': //出去数据
try{
int res=queue.getQueue();
System.out.printf("取出数据是%d",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h': //出去数据
try{
int res=queue.headQueue();
System.out.printf("队列的头数据是%d",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e': //退出
scanner.close();
loop=false;
break;
default:
break;
}
}
System.out.println("程序退出");
}


}

//使用数组模拟队列-编写一个ArrayQueue类
class ArrayQueue {
private int maxSize; //表示数组的最大容量
private int front; //执行队列头
private int rear; //队列尾
private int[] arr;//该数据用于存放数据,模拟队列

//创建队列的一个构造器
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1; //执行队列头部,分析出front时这指向队列头的前一个位置
rear = -1; //执行队列的尾部,即就是队列最后一个数据
}

//判断队列是否慢
public boolean isFull() {
return rear == maxSize - 1;
}

//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}

//添加数据到队列
public void addQueue(int n) {
//判断队列是否慢
if (isFull()) {
System.out.println("队列满,不能加入数据~");
return;
}
rear++;
arr[rear] = n;
}

//数据出队列
public int getQueue() {
//判断是否为空
if (isEmpty()) {
//通过抛出异常
throw new RuntimeException("队列空,不能取数据");
}
front++;
return arr[front];
}

//显示队列的所有数据
public void showQueue() {
//遍历数据
if (isEmpty()) {
System.out.println("队列为空,没有数据~~~");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n", i, arr[i]);
}
}

//显示队列头部数据,不是取出数据

public int headQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列没有数据");

}
return arr[front + 1];
}
}

循环队列

package com.csw.queue;

import java.util.Scanner;

/**
* @Auther: 行路
* @Date: Created on 2020/4/4 20:07 星期六
* @Description: com.csw.queue
* @version: 1.0
*/
public class CircleArrayQueueDemo {
public static void main(String[] args) {
//测试数组模拟环形队列
CircleQueue queue= new CircleQueue(4);
char key=' '; //接收用户输入
Scanner scanner = new Scanner(System.in);
boolean loop=true;
//输出一个菜单
while(loop){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
key=scanner.next().charAt(0); //接收一个字符
switch (key){
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("输入一个数字");
int value=scanner.nextInt();
queue.addQueue(value);
break;
case 'g': //出去数据
try{
int res=queue.getQueue();
System.out.printf("取出数据是%d",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h': //出去数据
try{
int res=queue.headQueue();
System.out.printf("队列的头数据是%d",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e': //退出
scanner.close();
loop=false;
break;
default:
break;
}
}
System.out.println("程序退出");
}
}
class CircleQueue{
private int maxSize; //表示数组的最大容量

//front 变量的含义做一个调整:front就指向队列的第一个元素,也就是arr[front]
//front 的初始值为=0
private int front; //执行队列头

//rear变量的含义做一个调整,rear指向队列的最后一个元素的后一个位置,因为希望空出一个位置
//rear 的初始值为=0
private int rear; //队列尾
private int[] arr;//该数据用于存放数据,模拟队列

public CircleQueue(int arrMaxSize) {
maxSize=arrMaxSize;
arr=new int[maxSize];
}

//判断队列是否满
public boolean isFull(){
return (rear+1)%maxSize==front;
}

//判断队列是否为空
public boolean isEmpty(){
return rear==front;
}

//填加数据
public void addQueue(int n){
//判断队列是否满
if(isFull()){
System.out.println("队列满,不能加入数据~");
return;
}

//直接将数据加入
arr[rear]=n;
//将rear后移,这里必须取模
rear=(rear+1)%maxSize;
}


//获取队列的数据,出队列
public int getQueue(){
//判断队列是否为空
if(isEmpty()){
//通过抛出异常
throw new RuntimeException("队列空,不能取数据");
}
//这里需要分析front是指向队列的第一个元素
//1.先把front对应的值保留到一个临时变量
//2.将front后移,考虑取余
//3.将零时的变量返回
int value=arr[front];
front=(front+1)%maxSize;
return value;
}

//显示队列的所有数据
public void showQueue(){
//遍历
if(isEmpty()){
System.out.println("队列空的,没有数据");
return;
}

for(int i=front;i<front+size();i++){
System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
}

}

//求出当前队列的有效数据个数
public int size(){

return (rear+maxSize-front)%maxSize;
}


//显示队列的头数据
public int headQueue(){
//判断
if(isEmpty()){
throw new RuntimeException("队列为空,没有数据");
}
return arr[front];
}
}
文章作者: Todcsw
文章链接: https://todcsw.github.io/2020/04/09/dataStructure-java%E5%AE%9E%E7%8E%B0%E5%BE%AA%E7%8E%AF%E9%98%9F%E5%88%97/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 行路のblog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论