环形队列的介绍和使用

一、环形队列是什么

环形队列是一种使用固定大小的数组、但逻辑上看起来首尾相连的队列结构。

它的最大特点:

  • 不会移动元素
  • 入队和出队只移动两个指针(front、rear)
  • 操作是 O(1)

极适合作为:缓冲区(Buffer)、生产者-消费者队列、高性能网络收发、音视频流处理、线程间通信等。

二、为什么要用环形队列

普通队列基于数组,会遇到一个问题:
出队时 front++,但前面的空间不能再利用 → 必须移动元素或重新分配。

环形队列的设计目的就是:

  • 避免数组移动
  • 让释放的空间可以再次使用

做到:既高效,又节省空间。

三、核心思想:余数取模 (mod)

假设数组长度为 capacity,队列中使用两个指针:

  • front 指向队头(第一个有效元素)
  • rear 指向队尾下一个可写入的位置

移动方式:

  • rear = (rear + 1) % capacity
  • front = (front + 1) % capacity

比如容量为 5:

索引:0 1 2 3 4  (length=5)

若 rear 从 4 再加 1:

(4 + 1) % 5 = 0

存储结构示意图:
在这里插入图片描述

四、环形队列的两个重要规则

判断队列是否为空

front == rear

判断队列是否满?
当 rear 的下一个位置是 front 时,队列为满。

(rear + 1) % capacity == front

队列最多容纳 capacity - 1 个元素。

五、核心操作(以浪费一个空间的经典方案为例)

1. 入队(enqueue)

if () return false;
buffer[rear] = value;
rear = (rear + 1) % capacity;

2. 出队(dequeue)

if () return false;
value = buffer[front];
front = (front + 1) % capacity;

完整示例:

#include <iostream>

using namespace std;

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

	~Queue()
	{
		delete[] pQue_;
		pQue_ = nullptr;
	}

	// 入队
	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!";
		}

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

	// 队空
	bool empty() 
	{
		return front_ == rear_;
	}

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

#if 0
		// 遍历一遍统计队列元素个数 O(n)
		int size = 0;
		for (int i = front_; i != rear_; i = (i + 1) % cap_) {
			size++;
		}

		return size;
#endif
	}

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;
		cap_ = size;
		front_ = 0;
		rear_ = i;
	}

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

int main()
{
	int arr[] = { 12, 4, 56, 7, 89, 31, 53, 75 };
	Queue que;

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

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

	que.push(100);
	que.push(200);
	que.push(300);

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

	while (!que.empty()) {
		cout << que.front() << " " << que.back() << endl;
		
		que.pop();
	}
}

输出结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值