队列
有序列表
先进先出(FIFO)
单向队列
基于数组实现
- 数组大小
- 数组
- 队头指针(front):指向队首元素的前一个位置
- 队尾指针(rear):指向队尾元素位置
判空条件:front == rear (单向队列有可能此情况也是满, 因为前面元素没有办法重复利用)
判满条件:rear == size - 1
代码实现
package org.example.data.structure.queue;
/**
* 基于数组实现队列
*
* @author xzy
* @since 2024/8/25 14:53
*/
public class ArrayQueue {
/**
* 队列头: 头部元素的前一个索引位置
*/
private Integer front;
/**
* 队列尾: 与尾部元素的索引位置在同一个
*/
private Integer rear;
/**
* 数组容量
*/
private Integer size;
/**
* 数组内容
*/
private Integer[] content;
/**
* 构造器创建数组
*/
public ArrayQueue(Integer size) {
this.size = size;
this.content = new Integer[size];
front = -1;
rear = -1;
}
/**
* 队列是否为空
*/
public Boolean isEmpty() {
return front == rear;
}
/**
* 队列是否已满
*/
public Boolean isFull() {
return rear == (size - 1);
}
/**
* 添加元素-入队
*/
public Boolean add(Integer data) {
if (isFull()) {
System.out.println("队列已满, 无法添加元素");
return false;
}
// 队尾索引+1
rear++;
content[rear] = data;
return true;
}
/**
* 移除元素-出队
*/
public Integer getData() {
if (isEmpty()) {
System.out.println("队列为空, 无数据需要出队");
return null;
}
front++;
Integer result = content[front];
// 原有位置赋空, 可以不赋值, 因为单向队列也不会再取值
content[front] = null;
return result;
}
/**
* 展示头部元素
*/
public Integer showHead() {
if (isEmpty()) {
return null;
}
return content[front + 1];
}
/**
* 展示尾部元素
*/
public Integer showRear() {
if (isEmpty()) {
return null;
}
return content[rear];
}
/**
* 展示队列中所有的元素
*/
public String toString() {
if (isEmpty()) {
return "";
}
StringBuilder str = new StringBuilder();
for (int i = front + 1; i <= rear; i++) {
str.append(content[i]).append("\t");
}
return str.toString();
}
}
循环队列
作用
为了弥补单向队列中只能一次利用的场景而出现。其中,实现循环队列有多种方式:
- 类型中增设表示元素个数的数据成员
- 牺牲一个单元来区分队空和队满,入队时少用一个队列单元
本次以第二种方式进行实现:
- 数组大小
- 数组
- 队首指针(front):指向队首元素,初始化为0
- 队尾指针(rear):指向队尾元素的后一个元素,初始化为0
判空条件:front == rear
判满条件:(rear + 1) % size == front
有效数据个数:(rear - front + size) % size
代码实现
package org.example.data.structure.queue;
/**
* 循环队列: 基于数组实现
*
* @author xzy
* @since 2024/8/25 17:12
*/
public class CircleArrayQueue {
/**
* 队首位置, 处于队列中第一个元素
*/
private int front;
/**
* 队尾位置, 处于队列中最后元素的后一位
*/
private int rear;
/**
* 循环数组
*/
private Integer[] content;
/**
* 循环数组大小, 该size会是content的大小, 其中size的大小会是content中真实元素个数 + 1, 即会存在一个空元素
*/
private int size;
public CircleArrayQueue(int size) {
// 初始化循环队列, 队首和队尾元素位置均从0位置开始
front = 0;
rear = 0;
this.size = size;
content = new Integer[size];
}
/**
* 判断队列是否为空
*/
public boolean isEmpty() {
return front == rear;
}
/**
* 判断队列是否已满
*/
public boolean isFull() {
return (rear + 1) % size == front;
}
/**
* 入队元素
*/
public boolean add(int data) {
if (isFull()) {
System.out.println("队列已满, 无法添加元素");
return false;
}
content[rear] = data;
// rear后移
rear = (rear + 1) % size;
return true;
}
/**
* 出队
*/
public Integer getData() {
if (isEmpty()) {
System.out.println("队列为空, 返回空数据");
return null;
}
int result = content[front];
content[front] = null;
front = (front + 1) % size;
return result;
}
/**
* 队列中的有效个数
*/
public int count() {
if (isEmpty()) {
return 0;
}
if (isFull()) {
return size - 1;
}
// 可以分两种情况, 其实可以化简为 (rear - front + size) % size
if (rear > front) {
return rear - front;
}
return rear - front + size;
}
/**
* 显示头元素
*/
public Integer showHead() {
if (isEmpty()) {
System.out.println("队列为空, 返回Null");
return null;
}
return content[front];
}
/**
* 显示尾元素
*/
public Integer showRear() {
if (isEmpty()) {
System.out.println("队列为空, 返回Null");
return null;
}
return content[(rear - 1 + size) % size];
}
/**
* 打印
*/
public String toString() {
if (isEmpty()) {
return "";
}
StringBuilder str = new StringBuilder();
if (rear < front) {
for (int i = front; i < size; i++) {
str.append(content[i]).append("\t");
}
for (int i = 0; i < rear; i++) {
str.append(content[i]).append("\t");
}
} else {
for (int i = front; i < rear; i++) {
str.append(content[i]).append("\t");
}
}
return str.toString();
}
}