使用数组实现队列

本文介绍了一个使用C++模板实现的固定大小队列类。该队列类支持基本的队列操作,如入队(push)、出队(pop)、获取队首元素(front)等,并通过模板使其实现类型泛化,可用于多种数据类型。文章提供了完整的类定义及一个简单的测试示例。
#include <iostream>
#include <cstdlib>
#include <cassert>

using namespace std;

template<class T> 
class queue {
public:
	typedef std::size_t size_type;
	typedef T value_type;
	static const size_type CAPACITY = 30;
	queue() {
		used = 0;
		first = 0;
		last = CAPACITY-1;
	}
	void push(const value_type& entry) {
		assert(size() < CAPACITY);
		last = next_index(last);
		data[last] = entry;
		used++;
	}
	void pop() {
		assert(!empty());
		first = next_index(first);
		used--;	
	}
	value_type front() {
		assert(!empty());
		return data[first];
		
	}
	bool empty() { return (used ==0); }
	size_type size() { return used; }
private:
	value_type data[CAPACITY];
	size_type used;
	size_type first;
	size_type last;
	size_type next_index(size_type i) const {
		return (i+1)%CAPACITY;
	}
};

int main() {
	queue<int> ique;
	for(int i = 0; i < 5; i++)
		ique.push(i);
	cout << "The size of the queue is: " << ique.size() << endl;
	while(!ique.empty()) {
		cout << ique.front() << endl;
		ique.pop();
	}
	return 0;
}

<think>我们使用数组实现队列时,需要解决假溢出问题,通常采用循环队列的方式。循环队列的关键点:1.使用固定大小的数组,两个指针:front和rear(或head和tail)分别指向队头和队尾。2.入队操作:将元素放入rear指向的位置,然后rear=(rear+1) %capacity3.出队操作:从front指向的位置取出元素,然后front =(front+1) %capacity4.判断队空:front ==rear5.判断队满:为了避免与队空条件混淆,通常有两种方法:a)使用一个额外的变量记录元素个数(size)b)或者牺牲一个存储单元,即队满条件为 (rear+1)% capacity== front这里我们选择使用一个size变量来记录当前队列中的元素个数,这样更直观。结构体定义:包含:数组(用指针动态分配)、容量(capacity)、队头索引(front)、队尾索引(rear)、当前元素个数(size)操作:创建队列:分配结构体内存,分配数组内存,初始化front=0,rear=0,size=0入队:检查是否满(size==capacity),不满则放入rear位置,rear循环后移,size加1出队:检查是否空(size==0),不空则取出front位置元素,front循环后移,size减1获取队头元素:类似出队但不移除释放队列:释放数组内存,释放结构体内存注意:由于是循环队列,rear和front在到达数组末尾时会回到开头(取模运算)。参考引用[1]和[2]中数组实现队列的方式,以及引用[3]中关于循环队列的描述。下面我们用C语言实现一个循环队列使用动态数组,并包含size变量。</think>### 数组实现循环队列(C语言) 以下是使用数组实现循环队列的完整代码方案,解决了传统数组队列的"假溢出"问题: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define QUEUE_CAPACITY 5 // 队列容量 // 队列结构体 typedef struct { int *data; // 存储数据的数组 int front; // 队头索引 int rear; // 队尾索引 int size; // 当前元素数量 int capacity; // 队列容量 } Queue; // 创建队列 Queue* createQueue() { Queue* queue = (Queue*)malloc(sizeof(Queue)); queue->capacity = QUEUE_CAPACITY; queue->data = (int*)malloc(queue->capacity * sizeof(int)); queue->front = 0; queue->rear = -1; queue->size = 0; return queue; } // 检查队列是否为空 bool isEmpty(Queue* queue) { return (queue->size == 0); } // 检查队列是否已满 bool isFull(Queue* queue) { return (queue->size == queue->capacity); } // 入队操作 void enqueue(Queue* queue, int value) { if (isFull(queue)) { printf("Queue is full! Cannot enqueue %d\n", value); return; } // 循环利用空间 queue->rear = (queue->rear + 1) % queue->capacity; queue->data[queue->rear] = value; queue->size++; } // 出队操作 int dequeue(Queue* queue) { if (isEmpty(queue)) { printf("Queue is empty!\n"); return -1; // 错误值 } int value = queue->data[queue->front]; queue->front = (queue->front + 1) % queue->capacity; queue->size--; return value; } // 获取队首元素 int front(Queue* queue) { if (isEmpty(queue)) { printf("Queue is empty!\n"); return -1; } return queue->data[queue->front]; } // 打印队列状态 void printQueue(Queue* queue) { printf("Queue ["); int count = queue->size; int index = queue->front; while (count--) { printf("%d", queue->data[index]); index = (index + 1) % queue->capacity; if (count > 0) printf(", "); } printf("]\n"); printf("Front: %d, Rear: %d, Size: %d/%d\n\n", queue->front, queue->rear, queue->size, queue->capacity); } // 释放队列内存 void freeQueue(Queue* queue) { free(queue->data); free(queue); } // 测试代码 int main() { Queue* q = createQueue(); // 测试入队 enqueue(q, 10); enqueue(q, 20); enqueue(q, 30); printQueue(q); // 测试出队 printf("Dequeued: %d\n", dequeue(q)); printQueue(q); // 测试循环利用空间 enqueue(q, 40); enqueue(q, 50); enqueue(q, 60); // 将填满队列 enqueue(q, 70); // 应显示队列已满 printQueue(q); // 测试出队所有元素 while (!isEmpty(q)) { printf("Dequeued: %d\n", dequeue(q)); } printQueue(q); freeQueue(q); return 0; } ``` ### 关键实现说明 1. **循环队列结构**: ```c typedef struct { int *data; // 动态数组 int front; // 队头索引 int rear; // 队尾索引 int size; // 当前元素数 int capacity; // 最大容量 } Queue; ``` 2. **解决假溢出**: - 通过模运算实现循环索引: ```c queue->rear = (queue->rear + 1) % queue->capacity; queue->front = (queue->front + 1) % queue->capacity; ``` - 当索引到达数组末尾时自动回到开头[^3] 3. **核心操作时间复杂度**: - 入队 $O(1)$:直接计算索引位置 - 出队 $O(1)$:移动队头索引 - 空间利用率 $O(n)$:固定大小的数组 4. **状态检测**: - 空队列:`size == 0` - 满队列:`size == capacity` - 避免使用`front == rear`判断,防止歧义[^2] ### 输出示例 ``` Queue [10, 20, 30] Front: 0, Rear: 2, Size: 3/5 Dequeued: 10 Queue [20, 30] Front: 1, Rear: 2, Size: 2/5 Queue is full! Cannot enqueue 70 Queue [20, 30, 40, 50, 60] Front: 1, Rear: 0, Size: 5/5 Dequeued: 20 Dequeued: 30 Dequeued: 40 Dequeued: 50 Dequeued: 60 Queue [] Front: 1, Rear: 0, Size: 0/5 ``` ### 适用场景 数组实现的循环队列特别适合: 1. 嵌入式系统(内存受限环境) 2. 实时系统(操作时间可预测) 3. 固定大小的缓冲区(如网络数据包队列) 4. 需要连续内存访问的场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值