1.队列的实现(Java内部的实现和数组实现)
/**
* 使用 Java 自带的链表(LinkedList)实现的队列。
* LinkedList 是一个双向链表,支持高效的元素添加和移除。
*/
public static class LinkQueue {
// 使用 LinkedList 来存储队列中的元素
public Queue<Integer> queue = new LinkedList<>();
/**
* 检查队列是否为空。
* @return 如果队列为空,返回 true;否则返回 false。
*/
public boolean isEmpty() {
return queue.isEmpty();
}
/**
* 向队列尾部添加一个元素。
* @param x 要添加的元素。
*/
public void add(int x) {
queue.offer(x);
}
/**
* 从队列头部移除并返回一个元素。
* @return 队列头部的元素。
*/
public int poll() {
return queue.poll();
}
/**
* 返回队列头部的元素,但不移除它。
* @return 队列头部的元素。
*/
Integer peek() {
return queue.peek();
}
/**
* 返回队列中元素的数量。
* @return 队列的大小。
*/
public int size() {
return queue.size();
}
}
/**
* 使用数组实现的队列。
*/
public static class ArrayQueue {
// 用于存储队列元素的数组
public int queue[];
// 队列头部的索引
public int l;
// 队列尾部的索引
public int r;
/**
* ArrayQueue 构造函数。
* @param nums 队列的初始容量。
*/
public ArrayQueue(int nums) {
queue = new int[nums];
l = 0;
r = 0;
}
/**
* 检查队列是否为空。
* @return 如果队列为空(l 和 r 相等),返回 true;否则返回 false。
*/
public boolean isEmpty() {
return l == r;
}
/**
* 向队列尾部添加一个元素。
* @param num 要添加的元素。
*/
public void offer(int num) {
queue[r++] = num;
}
/**
* 从队列头部移除并返回一个元素。
* @return 队列头部的元素。
*/
public int poll() {
return queue[l++];
}
/**
* 返回队列头部的元素,但不移除它。
* @return 队列头部的元素。
*/
int head() {
return queue[l];
}
/**
* 返回队列尾部的元素,但不移除它。
* @return 队列尾部的元素。
*/
public int tail() {
return queue[r - 1];
}
/**
* 返回队列中元素的数量。
* @return 队列中元素的数量(r - l)。
*/
public int size() {
return r - l;
}
}
2.栈的实现(Java内部的实现和数组实现)
// 直接用java内部的实现
// 其实就是动态数组,不过常数时间并不好
public static class Stack1 {
public Stack<Integer> stack = new Stack<>();
// 调用任何方法之前,先调用这个方法来判断栈内是否有东西
public boolean isEmpty() {
return stack.isEmpty();
}
public void push(int num) {
stack.push(num);
}
public int pop() {
return stack.pop();
}
public int peek() {
return stack.peek();
}
public int size() {
return stack.size();
}
}
// 实际刷题时更常见的写法,常数时间好
// 如果可以保证同时在栈里的元素个数不会超过n,那么可以用
// 也就是发生弹出操作之后,空间可以复用
// 一般笔试、面试都会有一个明确数据量,所以这是最常用的方式
public static class Stack2 {
public int[] stack;
public int size;
// 同时在栈里的元素个数不会超过n
public Stack2(int n) {
stack = new int[n];
size = 0;
}
// 调用任何方法之前,先调用这个方法来判断栈内是否有东西
public boolean isEmpty() {
return size == 0;
}
public void push(int num) {
stack[size++] = num;
}
public int pop() {
return stack[--size];
}
public int peek() {
return stack[size - 1];
}
public int size() {
return size;
}
}
3.循环队列
class MyCircularQueue {
// 存储队列中的元素
public int[] queue;
// 队列的左指针(头部),指向队列的第一个元素
public int l;
// 队列的右指针(尾部),指向队列的下一个插入位置
public int r;
// 队列中元素的数量
public int size;
// 队列的最大容量
public int limit;
// 构造函数,初始化循环队列的大小为 k
public MyCircularQueue(int k) {
queue = new int[k]; // 创建一个长度为 k 的数组用于存储队列元素
l = r = size = 0; // 初始化左右指针和大小为 0
limit = k; // 设置队列的最大容量为 k
}
// 入队操作,将 value 添加到队列尾部
public boolean enQueue(int value) {
if (isFull()) { // 如果队列已满,返回 false
return false;
} else {
queue[r] = value; // 将 value 添加到队列尾部
r = r == limit - 1 ? 0 : (r + 1); // 更新右指针,如果到达数组末尾则回到 0
size++; // 队列元素数量加 1
return true; // 成功添加,返回 true
}
}
// 出队操作,移除队列头部的元素
public boolean deQueue() {
if (isEmpty()) { // 如果队列为空,返回 false
return false;
} else {
l = l == limit - 1 ? 0 : (l + 1); // 更新左指针,如果到达数组末尾则回到 0
size--; // 队列元素数量减 1
return true; // 成功移除,返回 true
}
}
// 获取队列头部的元素,不移除它,如果队列为空返回 -1
public int Front() {
if (isEmpty()) { // 如果队列为空,返回 -1
return -1;
} else {
return queue[l]; // 返回队列头部的元素
}
}
// 获取队列尾部的元素,不移除它,如果队列为空返回 -1
public int Rear() {
if (isEmpty()) { // 如果队列为空,返回 -1
return -1;
} else {
int last = r == 0 ? (limit - 1) : (r - 1); // 计算队列尾部元素的索引
return queue[last]; // 返回队列尾部的元素
}
}
// 检查队列是否为空
public boolean isEmpty() {
return size == 0; // 如果元素数量为 0,则队列为空
}
// 检查队列是否已满
public boolean isFull() {
return size == limit; // 如果元素数量等于队列的最大容量,则队列已满
}
}