返回

深入浅出Leetcode622——设计循环队列

前端

在日常生活中,我们经常会用到循环队列,例如等待候车的人群、等候就餐的人群等等。它们都遵循着先进先出(FIFO)的原则,即最早进入队列的人员会最早离开队列。

Leetcode622题目要求设计一个循环队列,它具有以下特性:

  • 先进先出(FIFO) :最早进入队列的元素会最早离开队列。
  • 动态大小 :队列的大小可以动态地增加或减少。
  • 高效的操作 :入队和出队的操作都应该具有较高的效率。

循环队列的设计

循环队列可以采用数组来实现。为了使队列具有动态大小的特性,可以采用循环数组 的方式来组织数据。

循环数组是一种特殊的数组,它将数组的首尾相连,形成一个环形结构。这样,当队列到达数组的末尾时,它可以从数组的开头继续存储数据。

循环队列的操作

循环队列的操作主要包括入队和出队。

  • 入队 :将一个元素添加到队列的末尾。
  • 出队 :从队列的开头移除一个元素。

循环队列的入队和出队操作都是常数时间复杂度的,即无论队列的大小如何,这两个操作的时间开销都是相同的。

循环队列的应用

循环队列是一种非常常用的数据结构,它在各种场景下都有应用。例如:

  • 消息队列 :循环队列可以用来存储消息,以便应用程序可以异步地处理它们。
  • 任务队列 :循环队列可以用来存储任务,以便任务调度程序可以调度它们。
  • 缓冲区 :循环队列可以用来存储数据,以便应用程序可以平滑地处理数据流。

循环队列的代码实现

以下是一些常见编程语言中循环队列的代码实现:

JavaScript

class CircularQueue {
  constructor(size) {
    this.queue = new Array(size);
    this.head = 0;
    this.tail = 0;
    this.size = size;
  }

  enqueue(element) {
    if ((this.tail + 1) % this.size === this.head) {
      throw new Error("Queue is full");
    }
    this.queue[this.tail] = element;
    this.tail = (this.tail + 1) % this.size;
  }

  dequeue() {
    if (this.head === this.tail) {
      throw new Error("Queue is empty");
    }
    const element = this.queue[this.head];
    this.head = (this.head + 1) % this.size;
    return element;
  }

  isEmpty() {
    return this.head === this.tail;
  }

  isFull() {
    return (this.tail + 1) % this.size === this.head;
  }
}

Python

class CircularQueue:
  def __init__(self, size):
    self.queue = [None] * size
    self.head = 0
    self.tail = 0
    self.size = size

  def enqueue(self, element):
    if (self.tail + 1) % self.size == self.head:
      raise IndexError("Queue is full")
    self.queue[self.tail] = element
    self.tail = (self.tail + 1) % self.size

  def dequeue(self):
    if self.head == self.tail:
      raise IndexError("Queue is empty")
    element = self.queue[self.head]
    self.head = (self.head + 1) % self.size
    return element

  def isEmpty(self):
    return self.head == self.tail

  def isFull(self):
    return (self.tail + 1) % self.size == self.head

Java

public class CircularQueue<T> {
  private T[] queue;
  private int head;
  private int tail;
  private int size;

  public CircularQueue(int size) {
    this.queue = (T[]) new Object[size];
    this.head = 0;
    this.tail = 0;
    this.size = size;
  }

  public void enqueue(T element) {
    if ((tail + 1) % size == head) {
      throw new IllegalStateException("Queue is full");
    }
    queue[tail] = element;
    tail = (tail + 1) % size;
  }

  public T dequeue() {
    if (head == tail) {
      throw new IllegalStateException("Queue is empty");
    }
    T element = queue[head];
    head = (head + 1) % size;
    return element;
  }

  public boolean isEmpty() {
    return head == tail;
  }

  public boolean isFull() {
    return (tail + 1) % size == head;
  }
}

C++

template <typename T>
class CircularQueue {
public:
  CircularQueue(int size) : queue(size), head(0), tail(0), size(size) {}

  void enqueue(T element) {
    if ((tail + 1) % size == head) {
      throw std::runtime_error("Queue is full");
    }
    queue[tail] = element;
    tail = (tail + 1) % size;
  }

  T dequeue() {
    if (head == tail) {
      throw std::runtime_error("Queue is empty");
    }
    T element = queue[head];
    head = (head + 1) % size;
    return element;
  }

  bool isEmpty() {
    return head == tail;
  }

  bool isFull() {
    return (tail + 1) % size == head;
  }

private:
  std::vector<T> queue;
  int head;
  int tail;
  int size;
};

C#

public class CircularQueue<T> {
  private T[] queue;
  private int head;
  private int tail;
  private int size;

  public CircularQueue(int size) {
    queue = new T[size];
    head = 0;
    tail = 0;
    this.size = size;
  }

  public void Enqueue(T element) {
    if ((tail + 1) % size == head) {
      throw new InvalidOperationException("Queue is full");
    }
    queue[tail] = element;
    tail = (tail + 1) % size;
  }

  public T Dequeue() {
    if (head == tail) {
      throw new InvalidOperationException("Queue is empty");
    }
    T element = queue[head];
    head = (head + 1) % size;
    return element;
  }

  public bool IsEmpty() {
    return head == tail;
  }

  public bool IsFull() {
    return (tail + 1) % size == head;
  }
}

Ruby

class CircularQueue
  def initialize(size)
    @queue = Array.new(size)
    @head = 0
    @tail = 0
    @size = size
  end

  def enqueue(element)
    if (@tail + 1) % @size == @head
      raise "Queue is full"
    end
    @queue[@tail] = element
    @tail = (@tail + 1) % @size
  end

  def dequeue
    if @head == @tail
      raise "Queue is empty"
    end
    element = @queue[@head]
    @head = (@head + 1) % @size
    return element
  end

  def isEmpty?
    @head == @tail
  end

  def isFull?
    (@tail + 1) % @size == @head
  end
end

PHP

class CircularQueue {
  private $queue;