1 队列
队列在现实生活中的应用:
队列是一个有序列表,可以用数组或链表实现
队列最大的特点是先入先出
1.1 使用数组模拟队列
采用两个指针,front指向当前队列队首,rear指向当前队列队尾
当元素入队列时:
front不动,rear后移
当元素出队列时:
front后移,rear不动
代码实现:
/**
* @author 雫
* @date 2021/3/14 - 18:59
* @function 数组模拟队列
*/
@SuppressWarnings("all")
public class MyQueue {
private int maxSize;
private int front;
private int rear;
private int[] arr;
/*初始化队列,最大长度为maxSize*/
public MyQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
front = 0;
rear = 0;
}
/*向队列中增加元素,每增加一个元素,rear向后移动一次
* 当rear的值等与maxSize时,队列满*/
public void add(int num) {
if(isFull()) {
throw new RuntimeException("当前队列已满");
}
arr[rear] = num;
rear++;
}
/*从队列中取出元素,每取出一个元素,front向后移动一次
* 当front的值等于rear的值时,队列空*/
public int get() {
if(isEmpty()) {
throw new RuntimeException("当前队列已空");
}
int value = arr[front];
front++;
return value;
}
/*打印当前队列内的所有元素*/
public void showQueue() {
if(isEmpty()) {
throw new RuntimeException("当前队列为空");
}
for(int i = this.front; i < this.rear; i++) {
System.out.println(arr[i]);
}
}
/*获取当前队列的队首元素*/
public int peek() {
if(isEmpty()) {
throw new RuntimeException("当前队列为空");
}
int value = arr[front];
return value;
}
/*队列判满*/
public boolean isFull() {
if(this.rear == maxSize) {
return true;
}
return false;
}
/*队列判空*/
public boolean isEmpty() {
if(this.rear == this.front) {
return true;
}
return false;
}
}
上述数组模拟的队列最大的问题是:当get()后,需要从队列中取出的元素并没有真正从队列中取出来,仍然占用着先前的空间,导致add()的失败,这并不是一个真正有效的队列
1.2 数组模拟环形队列
仍然采用两个指针,front和rear
当元素入队列时:
front不动,rear向后移动,rear指向最后一个元素的下一个位置
arr[rear+1]为空不使用,作为一个判断标志
队列的实际容量为 maxSize - 1
当元素出队列时:
rear不动,front向后移动,arr[front]永远是队首元素
当(rear+1) % maxSize == front时,当前队列已满
即rear赶了一圈追上了front
当front == rear时,当前队列为空
即一开始为空,或者front追了一圈追到了rear
当前队列中有效元素的个数:
(rear + maxSize - front) % maxSize
代码实现:
/**
* @author 雫
* @date 2021/3/14 - 20:28
* @function 环形队列
*/
@SuppressWarnings("all")
public class MyLoopQueue {
private int maxSize;
private int front;
private int rear;
private int[] arr;
/*最大空间实际为maxSize-1,arr[rear + 1]作为标志*/
public MyLoopQueue(int maxSize) {
this.maxSize = maxSize;
this.front = 0;
this.rear = 0;
this.arr = new int[this.maxSize];
}
/*增加元素,每次增加前判断队列是否已满
* 通过取模运算保证rear的循环指向,避免下标越界*/
public void add(int num) {
System.out.println(num);
if(isFull()) {
throw new RuntimeException("队列已满");
}
arr[rear] = num;
rear = (rear + 1) % maxSize;
}
/*获取元素,返回当前front所指向的值
* 通过取模来保证front的循环指向,避免下标越界*/
public int get() {
if(isEmpty()) {
throw new RuntimeException("队列为空");
}
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
/*打印当前队列中的所有元素
* 从front开始遍历,取模避免下标越界*/
public void showQueue() {
if(isEmpty()) {
throw new RuntimeException("当前队列为空");
}
for(int i = front; i < front + size(); i++) {
System.out.println(arr[i % maxSize]);
}
}
/*取得当前队列中有效元素*/
public int size() {
return (rear + maxSize - front) % maxSize;
}
/*获取队首元素*/
public int peek() {
if(isEmpty()) {
throw new RuntimeException("当前队列为空");
}
return arr[front];
}
/*判满*/
public boolean isFull() {
if((rear + 1) % maxSize == front) {
return true;
}
return false;
}
/*判空*/
public boolean isEmpty() {
if(rear == front) {
return true;
}
return false;
}
}