循环队列(数组实现)
数据结构:循环队列(数组实现)
首先准备基本类
class CircleArray {
private int maxSize; //表示队列的最大容量
//front 就指向队列的第一个元素,也就是说arr[front]
//front 初始值 0
private int front;
//rear 指向队列的最后一个元素的后一个位置
//rear 的初始值 0
private int rear;
private int[] arr; //用于存储数据,模拟队列
public CircleArray(int arrMaxSize) {
this.maxSize = arrMaxSize;
arr = new int[maxSize];
}
}
入队
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列满,不能加入数据!");
return;
}
//直接将数据加入
arr[rear] = n;
//让rear后移,这里必须取模,考虑数组下标越界
rear = (rear + 1) % maxSize;
}
rear指向的是队尾元素的后一个位置,与数组大小取模可以解决下标越界问题
因为是指向的后一个位置,所以在添加时可以先存入数组,再移动下标
出队
public int getQueue() {
//判断队列是否空
if (isEmpty()) {
//通过抛出异常
throw new RuntimeException("队列空,不能取数据");
}
int val = arr[front];
front = (front + 1) % maxSize;
return val;
}
front直接指向的就是队首的位置,因为是循环队列,同样要考虑下标越界
出队后,要向后移动下标,所以不能直接return出队的元素,先保存出队元素
再移动front,最后return保存的出队元素
获取队首元素
public int peekQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列空,没有数据");
}
return arr[front];
}
获取队列中元素个数
public int size() {
return (rear + maxSize - front) % maxSize;
}
需要注意的是:
rear的索引在front前面的情况,在普通队列中rear的索引大于front,可以通过简单的rear - front得出元素个数
但是循环队列会出现rear的索引小于front的情况,简单的相减会出现负数的情况,显然不符合要求,
利用rear+maxSize可使rear的索引大于front,然后相减的结果 % maxSize ,
(rear + maxSize - front) % maxSize == rear - front
遍历循环队列
public void showQueue() {
//遍历
if (isEmpty()) {
System.out.println("队列空,没有数据!");
return;
}
// 思路:从front开始遍历,遍历多少个元素
for (int i = front; i < front + size(); i++) {
int index = i % maxSize;
System.out.printf("arr[%d]=%d\n", index, arr[index]);
}
}
思路:算出队列有效元素个数,从front位置开始打印,下标向后移动,取模防止下标越界,循环遍历数组
isFull()
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
数组不填满,队首和队尾之间空一个位置,即当元素存储到队列倒数第二个元素时,rear指向最后一个位置,
此时(rear + 1) % maxSize == front
isEmpty()
public boolean isEmpty() {
return rear == front;
}