思路转自循环队列

思路解析

该数据结构是一个环,这个环我们可以用数组来模拟。对于循环队列,队列中的任何位置都可以作为队列头,并且队尾位置可以用下式求得:
tailIndex = (headIndex+count-1)%capacity
其中,count是队列长度,capacity是队列容量
以下用python进行模拟。

方法一:数组

算法

设计数据结构的关键是如何设计 属性,好的设计属性数量更少。

属性数量少说明属性之间冗余更低。

属性冗余度越低,操作逻辑越简单,发生错误的可能性更低。

属性数量少,使用的空间也少,操作性能更高。

但是,也不建议使用最少的属性数量。一定的冗余可以降低操作的时间复杂度,达到时间复杂度和空间复杂度的相对平衡。

根据以上原则,列举循环队列的每个属性,并解释其含义。

queue:一个固定大小的数组,用于保存循环队列的元素。

headIndex:一个整数,保存队首 head 的索引。

count:循环队列当前的长度,即循环队列中的元素数量。使用 headIndex 和 count 可以计算出队尾元素的索引,因此不需要队尾属性。

capacity:循环队列的容量,即队列中最多可以容纳的元素数量。该属性不是必需的,因为队列容量可以通过数组属性得到,但是由于该属性经常使用,所以我们选择保留它。这样可以不用在 Python 中每次调用 len(queue) 中获取容量。但是在 Java 中通过 queue.length 获取容量更加高效。为了保持一致性,在两种方案中都保留该属性。

class MyCircularQueue:

  def __init__(self, k: int):
      """
      Initialize your data structure here. Set the size of the queue to be k.
      """
      self.queue = [0]*k
      self.headIndex = 0
      self.count = 0
      self.capacity = k

  def enQueue(self, value: int) -> bool:
      """
      Insert an element into the circular queue. Return true if the operation is successful.
      """
      if self.count == self.capacity:
          return False
      self.queue[(self.headIndex + self.count) % self.capacity] = value
      self.count += 1
      return True

  def deQueue(self) -> bool:
      """
      Delete an element from the circular queue. Return true if the operation is successful.
      """
      if self.count == 0:
          return False
      self.headIndex = (self.headIndex + 1) % self.capacity
      self.count -= 1
      return True

  def Front(self) -> int:
      """
      Get the front item from the queue.
      """
      if self.count == 0:
          return -1
      return self.queue[self.headIndex]

  def Rear(self) -> int:
      """
      Get the last item from the queue.
      """
      # empty queue
      if self.count == 0:
          return -1
      return self.queue[(self.headIndex + self.count - 1) % self.capacity]

  def isEmpty(self) -> bool:
      """
      Checks whether the circular queue is empty or not.
      """
      return self.count == 0

  def isFull(self) -> bool:
      """
      Checks whether the circular queue is full or not.
      """
      return self.count == self.capacity

c++版

class MyCircularQueue {
private:
  vector<int> data;
  int head;
  int tail;
  int size;
public:
  /** Initialize your data structure here. Set the size of the queue to be k. */
  MyCircularQueue(int k) {
      data.resize(k);
      head = -1;
      tail = -1;
      size = k;
  }
  
  /** Insert an element into the circular queue. Return true if the operation is successful. */
  bool enQueue(int value) {
      if (isFull()) {
          return false;
      }
      if (isEmpty()) {
          head = 0;
      }
      tail = (tail + 1) % size;
      data[tail] = value;
      return true;
  }
  
  /** Delete an element from the circular queue. Return true if the operation is successful. */
  bool deQueue() {
      if (isEmpty()) {
          return false;
      }
      if (head == tail) {
          head = -1;
          tail = -1;
          return true;
      }
      head = (head + 1) % size;
      return true;
  }
  
  /** Get the front item from the queue. */
  int Front() {
      if (isEmpty()) {
          return -1;
      }
      return data[head];
  }
  
  /** Get the last item from the queue. */
  int Rear() {
      if (isEmpty()) {
          return -1;
      }
      return data[tail];
  }
  
  /** Checks whether the circular queue is empty or not. */
  bool isEmpty() {
      return head == -1;
  }
  
  /** Checks whether the circular queue is full or not. */
  bool isFull() {
      return ((tail + 1) % size) == head;
  }
};

/**
* Your MyCircularQueue object will be instantiated and called as such:
* MyCircularQueue obj = new MyCircularQueue(k);
* bool param_1 = obj.enQueue(value);
* bool param_2 = obj.deQueue();
* int param_3 = obj.Front();
* int param_4 = obj.Rear();
* bool param_5 = obj.isEmpty();
* bool param_6 = obj.isFull();
*/