队列

23 阅读2分钟

环形队列

我们使用first和rear指向第一个元素,假设我们使用数组实现队列,长度为7,每当队列中添加新元素的时候rear指向(rear + 1) % 7,从队列取数据的时候(first + 1) % 7,这样实现了一个环形队列。并且当(rear + 1) % 7 == first的时候我们判断队列满了。

代码

#include <iostream>

using namespace std;



class Queue {
  public:
    Queue(int size = 10)
          : cap_(size)
          , front_(0)
          , rear_(0)
          , size_(0)
    {
      pQue_ = new int[size];
    }
    ~Queue() {
      delete[] pQue_;
      pQue_ = nullptr;
    }

  public:
    // 入队操作
    void push(int val) {
      // 队列如果满了的话进行扩容操作
      if ((rear_ + 1) % cap_ == front_) {
        expand(2 * cap_);
      }

      pQue_[rear_] = val;
      rear_ = (rear_ + 1) % cap_;
      size_++;
    }

    // 出队
    void pop() {
      // 队列为空
      if (front_ == rear_) {
        throw "Queue is empty!";
      }

      front_ = (front_ + 1) % cap_;
      size_--;

    }

    // 获取队头元素
    int front() const{
      // 队列为空
      if (front_ == rear_) {
        throw "Queue is empty!";
      }

      return pQue_[front_];
    }

    // 获取队尾元素
    int back() const {
       // 队列为空
      if (front_ == rear_) {
        throw "Queue is empty!";
      }


      // 注意rear在0位置的特殊情况,因此我们使用(rear_ - 1 + cap_) % cap_

      return pQue_[(rear_ - 1 + cap_) % cap_];
    }

    // 队列是否为空
    int empty() const {
      return front_ == rear_;
    }

    // 队列元素的个数
    int size() const {
      return size_;
    }

  private:
    // 扩容操作
    void expand(int size) {
      int* p = new int[size];

      int i = 0;  // 用来访问新的内存

      int j = front_;

      // 从队头遍历到队尾拷贝元素到新内存中
      for (; j != rear_; i++, j = (j + 1) % cap_)
      {
        p[i] = pQue_[j];
      }

      delete[] pQue_;
      pQue_ = p;
      front_ = 0;
      rear_ = i;
      cap_ = size;
      
    }
    

  private:
    int* pQue_;
    int cap_;   // 空间容量
    int front_;  // 队头
    int rear_;   // 队尾
    int size_;   // 个数
};



int main() {

  int arr[] = {10, 67, 98, 78, 45, 32, 11};
  Queue que;

  for(int v : arr) {
    que.push(v);
  }

  cout << que.front() << endl;
  cout << que.back() << endl;

  que.push(16);
  que.push(21);
  que.push(13);


  cout << que.front() << endl;
  cout << que.back() << endl;

  

  return 0;

}

测试

➜  build git:(main) ✗ ./CircleQueue 
10
11
10
13

链式队列

我们使用双向循环链表实现链式队列

代码

#include <iostream>

using namespace std;

class LinkQueue {

  public:
    LinkQueue() {
      head_ = new Node();
      head_->next_ = head_;
      head_->pre_ = head_;

    }
    ~LinkQueue() {
      Node*p = head_->next_;

      while (p != head_)
      {
        head_->next_ = p->next_;
        p->next_->pre_ = head_;
        delete p;
        p = head_->next_;
      }

      delete head_;
      head_ = nullptr;
      
    }
  public:
    // 入队
    void push(int val) {
      Node* p = head_->pre_;  // 当前末尾结点

      Node* node = new Node(val);

      node->pre_ = p;
      node->next_ = head_;
      p->next_ = node;
      head_->pre_ = node;

    }

    // 出队, 删除第一个结点
    void pop() {
      Node* p = head_->next_;
      head_->next_ = p->next_;
      p->next_->pre_ = head_;
      delete p;
    }

    // 获取队头元素
    int front() const {
      if (head_->next_ == head_) {
        throw "queue is empty";
      }
      return head_->next_->data_;
    }

    // 获取队尾元素
    int back() const {
      if (head_->pre_ == head_) {
        throw "queue is empty";
      }
      return head_->pre_->data_;
    }

    // 判空
    bool empty() const {
      return head_->next_ = head_;
    }




  private:
    struct Node {
      Node(int data = 0): data_(data), next_(nullptr), pre_(nullptr) {};
      int data_;
      Node* next_;
      Node* pre_;
    };

    Node* head_;  // 指向头节点
};

int main() {

  int arr[] = {10, 67, 98, 78, 45, 32, 11};
  LinkQueue que;

  for(int v : arr) {
    que.push(v);
  }

  cout << que.front() << endl;
  cout << que.back() << endl;

  que.push(16);
  que.push(21);
  que.push(13);


  cout << que.front() << endl;
  cout << que.back() << endl;

  

  return 0;

}

测试

➜  build git:(main) ✗ ./LinkQueue 
10
11
10
13