【Java数据结构】循环队列的数组实现
先上一个初级队列的数组实现,缺点是数组不能复用,没有可用性
public class ArrayQueue {
private int maxSize;//表示数组最大容量
private int front;//队列头下标
private int rear;//队列尾
private int[] arr;
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
front = -1;//指向队列头部,指向队列头的前一个位置
rear = -1;//指向队列尾部,指向尾部数据
}
private boolean isFull(){
return rear == maxSize-1;
}
private boolean isEmpty(){
return front == rear;
}
public void addItem(int item){
if(isFull()){
System.out.println("队列满");
return;
}
rear++;
arr[rear] = item;
}
public int getItem(){
if(isEmpty()){
throw new RuntimeException("队列空,无法出队");
}
front++;
return arr[front];
}
public void show(){
if(isEmpty()){
System.out.println("队列空");
return;
}
for (int i = front+1; i <= rear; i++) {
System.out.print(arr[i]+" ");
}
}
public void showFront(){
if(isEmpty()){
System.out.println("队列空");
throw new RuntimeException("队列空!");
}
System.out.println(arr[front+1]);
}
}
于是乎,我们要考虑循环一个数组来实现循环队列,即想办法把用过的位置复用
在上面的代码中,重点是两个下标front和rear,分别指向头和尾,要想复用,就得想办法将rear重新指向数组开始的位置
接下来上我的第一个思路
毫无疑问能想到的肯定是取模,我的思路是,让front和rear一直增长,而通过对maxSize进行取模来控制其取模后的值一直在0到maxSize之间变化
第一个思路的代码如下,在代码中进行部分思路讲解
/**
* @author ZhiYi Li
* @create 2020/8/24 19:05
* 循环队列的数组实现
* 思路:
* 1、front指向第一个元素,初始值为0
* 2、rear指向队列的最后一个元素的后一个位置,特意空出一个空间,初始值为0
* 3、当队列满时,(rear+1)%maxSize = front
* 4、当队列空时,rear=front
*/
public class CycleArrayQueue {
private int maxSize;
private int front;//指向第一个元素的位置
private int rear;//指向最后一个元素的后一个位置
private int[] ints;
public CycleArrayQueue(int maxSize) {
this.maxSize = maxSize+1;//预留一个空位置
ints = new int[this.maxSize];
front = 0;
rear = 0;
}
private boolean isFull(){
return (rear + 1) % maxSize == front;
}
private boolean isEmpty(){
return front == rear;
}
public void addItem(int item){
if(isFull()){
System.out.println("队列满!");
return;
}
ints[rear%maxSize] = item;
rear++;
}
public int getItem(){
if (isEmpty()){
System.out.println("队列空!");
}
int result = ints[front%maxSize];
front++;
return result;
}
public void show(){
if(isEmpty()){
System.out.println("队列空!");
return;
}
for (int i = front; i < rear; i++) {
System.out.println(ints[i%maxSize]+" ");
}
}
public void showFront(){
if (isEmpty()){
System.out.println("队列空!");
}
System.out.println("头数据为:"+ints[front%maxSize]);
}
public int size(){
return (rear+maxSize-front)%maxSize;
}
}
//以下是测试
class Main2{
public static void main(String[] args) {
CycleArrayQueue queue = new CycleArrayQueue(5);
queue.addItem(2);
queue.addItem(3);
queue.addItem(4);
queue.addItem(5);
queue.addItem(6);
System.out.println("队列初始值:");
queue.show();
System.out.println("出队列");
System.out.println(queue.getItem());
System.out.println("一次出队列后的结果");
queue.show();
queue.addItem(7);
System.out.println("一次进队列的结果:");
queue.show();
System.out.println("五次出队后:");
for (int i = 0; i < 5; i++) {
queue.getItem();
}
queue.show();
queue.addItem(567);
System.out.println("一次进队:");
queue.show();
queue.showFront();
}
}
这种思路是可以通过简单的测试的,但是这种思路会有一个大问题,front和rear都是int型,而int型是有范围上限的(-2147483648到2147483648),所以不能让它一直增长,在数据量大时容易出错
改良的思路是我们可以用取模将front和rear的值保持在范围内
代码如下:
/**
* @author ZhiYi Li
* @create 2020/8/24 19:05
* 循环队列的数组实现
* 思路:
* 1、front指向第一个元素,初始值为0
* 2、rear指向队列的最后一个元素的后一个位置,特意空出一个空间,初始值为0
* 3、当队列满时,(rear+1)%maxSize = front
* 4、当队列空时,rear=front
*/
public class CycleArrayQueue {
private int maxSize;
private int front;//指向第一个元素的位置
private int rear;//指向最后一个元素的后一个位置
private int[] ints;
public CycleArrayQueue(int maxSize) {
this.maxSize = maxSize+1;//预留一个空位置
ints = new int[this.maxSize];
front = 0;
rear = 0;
}
private boolean isFull(){
return (rear + 1) % maxSize == front;
}
private boolean isEmpty(){
return front == rear;
}
public void addItem(int item){
if(isFull()){
System.out.println("队列满!");
return;
}
ints[rear] = item;
rear=(rear + 1)%maxSize;
}
public int getItem(){
if (isEmpty()){
System.out.println("队列空!");
}
int result = ints[front];
front = (front+1)%maxSize;
return result;
}
public void show(){
if(isEmpty()){
System.out.println("队列空!");
return;
}
//注意遍历时rear会小于front,不能简单的循环遍历
for (int i = front; i < front +size(); i++) {
System.out.println(ints[i%maxSize]+" ");
}
}
public void showFront(){
if (isEmpty()){
System.out.println("队列空!");
}
System.out.println("头数据为:"+ints[front%maxSize]);
}
public int size(){
return (rear+maxSize-front)%maxSize;
}
}
//以下是测试
class Main2{
public static void main(String[] args) {
CycleArrayQueue queue = new CycleArrayQueue(5);
queue.addItem(2);
queue.addItem(3);
queue.addItem(4);
queue.addItem(5);
queue.addItem(6);
System.out.println("队列初始值:");
queue.show();
System.out.println("出队列");
System.out.println(queue.getItem());
System.out.println("一次出队列后的结果");
queue.show();
queue.addItem(7);
System.out.println("一次进队列的结果:");
queue.show();
System.out.println("五次出队后:");
for (int i = 0; i < 5; i++) {
queue.getItem();
}
queue.show();
queue.addItem(567);
System.out.println("一次进队:");
queue.show();
queue.showFront();
}
}
需要注意的点是在show方法时,我们在第一种代码的show方法的思路上可以发现,第一种show方法的rear实际上就是front+size
完。

浙公网安备 33010602011771号