环形队列
我们使用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