700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > JAVA数据结构与算法【队列 数组模拟(环形)队列】

JAVA数据结构与算法【队列 数组模拟(环形)队列】

时间:2019-01-18 05:21:03

相关推荐

JAVA数据结构与算法【队列 数组模拟(环形)队列】

队列

使用场景:排队

队列介绍

队列是一个有序列表,可以用数组或是链表来实现。遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出示意图:(使用数组模拟队列示意图)

数组模拟队列

队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变,如图所示:

数组模拟队列

当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:思路分析

将尾指针往后移:rear+1 , 当front == rear 【空】若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1[队列满]

代码实现

package com.henu.queue;import java.util.Scanner;/*** @author George* @description**/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\n",res);}catch (Exception e){System.out.println(e.getMessage());}break;case 'h':try {int res = queue.headQueue();System.out.printf("队列头的数据是%d\n",res);} catch (Exception e) {System.out.println(e.getMessage());}break;case 'e':scanner.close();loop = false;break;default:break;}}}}//使用数组模拟队列-编写一个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++;//让rear后移arr[rear] = n;}//获取队列的数据,出队列public int getQueue(){//判断队列是否为空if (isEmpty()) {//抛出异常throw new RuntimeException("队列空,不能取出数据");}front++;//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.henu.queue;import java.util.Scanner;/*** @author George* @description 环形队列**/public class CircleArrayQueueDemo {public static void main(String[] args) {//测试System.out.println("测试数据模拟环形队列");//创建一个环形队列CircleArray queue = new CircleArray(4);//设置为4,其队列的最大有效长度是3char 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\n",res);}catch (Exception e){System.out.println(e.getMessage());}break;case 'h':try {int res = queue.headQueue();System.out.printf("队列头的数据是%d\n",res);} catch (Exception e) {System.out.println(e.getMessage());}break;case 'e':scanner.close();loop = false;break;default:break;}}System.out.println("程序退出");}}class CircleArray{private int maxSize;//表示数组的最大容量//front 变量的含义做一个调整:front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素//front的初始值 = 0private int front;//rear 变量的含义做出调整:rear指向队列最后一个元素的后一个位置,因为希望空出一个空间作为约定//rear 的初始值 = 0private int rear;//队列尾private int[] arr;//该数据用于存放数据,模拟队列public CircleArray(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 int size(){//rear = 2//front = 1//maxSize = 3return (rear+maxSize-front)%maxSize;}//显示队列中的所有元素public void showQueue(){//遍历if (isEmpty()){System.out.println("队列空的,没有数据~");return;}//思路:从front考试遍历,遍历多少个元素//动脑筋for (int i = front; i < front+size(); i++) {System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);}}public int headQueue(){//判断if (isEmpty()) {throw new RuntimeException("队列空的,没有数据~");}return arr[front];}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。