Java队列实现咨询:如何实现数组的队列式元素移位?
修复你的Java队列实现(实现FIFO逻辑)
嘿,你的这段代码其实是个**栈(LIFO,后进先出)**而非队列!因为dequeue()方法直接从数组末尾取元素,完全是栈的弹出逻辑。要改成真正的队列(FIFO,先进先出),让新元素添加到队尾、移除时取最早加入的元素,甚至在队列满时自动挤出最早元素,我给你两种可行的修改方案:
方案1:简单数组移位(入门易懂)
这个方案逻辑非常直观,适合刚接触队列概念的同学理解核心原理,但缺点是每次出队都要移动数组内的后续元素,数据量较大时效率会偏低(时间复杂度O(n))。
修改要点:
- 保留
enqueue()的逻辑(往数组尾部添加元素,满了自动扩容); - 重写
dequeue():先取出数组第一个元素(最早加入的元素),再将后续所有元素向前移位一位,最后更新队列大小; - 增加空队列判断,避免数组越界报错。
修改后的完整代码:
public class Queue { private int[] elements; private int size; public static final int DefCap = 8; public Queue() { this(DefCap); } public Queue(int capacity) { elements = new int[capacity]; } public int[] enqueue(int v) { if (size >= elements.length) { int[] a = new int[elements.length * 2]; System.arraycopy(elements, 0, a, 0, elements.length); elements = a; } elements[size++] = v; return elements; } public int dequeue() { if (empty()) { throw new IllegalStateException("Queue is empty"); } // 取出队首的最早元素 int frontElement = elements[0]; // 将后续元素整体向前移位一位 System.arraycopy(elements, 1, elements, 0, size - 1); // 清空最后一个位置的冗余值(可选,避免残留旧数据) elements[--size] = 0; return frontElement; } public boolean empty() { return size == 0; } public int getSize() { return size; } }
方案2:循环数组(环形缓冲区,高效版)
如果需要更高的效率(入队出队均为O(1)时间复杂度),或者要实现固定容量、满队时新元素自动挤出最早元素的逻辑,推荐使用环形缓冲区方案。我们用front指针记录队首位置,rear指针记录队尾的下一个插入位置,通过模运算实现数组空间的循环复用。
修改要点:
- 新增
front和rear两个指针; - 入队时:如果队列已满,直接移动
front指针(挤出最早元素),再插入新元素;如果未满,正常插入并更新指针; - 出队时:直接取
front指针位置的元素,再移动front指针更新队首。
修改后的完整代码(固定容量,满队挤最早元素):
public class Queue { private int[] elements; private int front; private int rear; private int size; public static final int DefCap = 8; public Queue() { this(DefCap); } public Queue(int capacity) { elements = new int[capacity]; front = 0; rear = 0; size = 0; } // 入队:满队时自动挤出最早加入的元素 public void enqueue(int v) { elements[rear] = v; rear = (rear + 1) % elements.length; // 队列已满时,移动front指针挤掉最早元素,size保持不变 if (size == elements.length) { front = (front + 1) % elements.length; } else { size++; } } public int dequeue() { if (empty()) { throw new IllegalStateException("Queue is empty"); } int frontElement = elements[front]; front = (front + 1) % elements.length; size--; return frontElement; } public boolean empty() { return size == 0; } public int getSize() { return size; } // 可选:获取队列的固定容量 public int getCapacity() { return elements.length; } }
额外说明:
- 这个版本是固定容量队列,满队后新元素会自动覆盖最早加入的元素;
- 如果想要保留自动扩容的逻辑,也可以在
enqueue()中判断size == elements.length时,扩容数组并重新排列元素,再更新front和rear指针。
测试验证
你可以用以下代码测试两种方案的逻辑:
public static void main(String[] args) { Queue queue = new Queue(3); // 用方案2时,小容量更易测试挤元素逻辑 queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); System.out.println(queue.dequeue()); // 应输出1(最早加入的元素) queue.enqueue(4); System.out.println(queue.dequeue()); // 应输出2 System.out.println(queue.dequeue()); // 应输出3 System.out.println(queue.dequeue()); // 应输出4 }
内容的提问来源于stack exchange,提问作者06ov
相关产品推荐
相关产品推荐

