code review!
/* 实现的最简单的ringbuff 有更多提升空间,可以留言说明 */
#include "stdio.h"
#include "stdlib.h"
#define LEN 10
/*环形队列结构体*/
typedef struct ring_buff{
int array[LEN];
int W;
int R;
}*ring;
/*环形队列初始化*/
struct ring_buff * fifo_init(void)
{
struct ring_buff * p = NULL;
p = (struct ring_buff *)malloc(sizeof(struct ring_buff));
if(p == NULL)
{
printf("fifo_init malloc error\n");
return NULL;
}
p->W = 0;
p->R = 0;
return p;
}
/*判断环形队列是否已经满了*/
int get_ring_buff_fullstate(struct ring_buff * p_ring_buff)
{
/*如果写位置减去读位置等于队列长度,就说明这个环形队列已经满*/
if((p_ring_buff->W - p_ring_buff->R) == LEN)
{
return (1);
}
else
{
return (0);
}
}
/*判断环形队列为空*/
int get_ring_buff_emptystate(struct ring_buff * p_ring_buff)
{
/*如果写位置和读的位置相等,就说明这个环形队列为空*/
if(p_ring_buff->W == p_ring_buff->R)
{
return (1);
}
else
{
return (0);
}
}
/*插入数据*/
int ring_buff_insert(struct ring_buff * p_ring_buff,int data)
{
if(p_ring_buff == NULL)
{
printf("p null\n");
return (-1);
}
if(get_ring_buff_fullstate(p_ring_buff) == 1)
{
printf("buff is full\n");
return (-2);
}
p_ring_buff->array[p_ring_buff->W%LEN] = data;
p_ring_buff->W ++;
//printf("inset:%d %d\n",data,p_ring_buff->W);
return (0);
}
/*读取环形队列数据*/
int ring_buff_get(struct ring_buff * p_ring_buff)
{
int data = 0;
if(p_ring_buff == NULL)
{
printf("p null\n");
return (-1);
}
if(get_ring_buff_emptystate(p_ring_buff) == 1)
{
printf("buff is empty\n");
return (-2);
}
data = p_ring_buff->array[p_ring_buff->R%LEN];
p_ring_buff->R++;
return data;
}
/*销毁*/
int ring_buff_destory(struct ring_buff * p_ring_buff)
{
if(p_ring_buff == NULL)
{
printf("p null\n");
return (-1);
}
free(p_ring_buff);
return (0);
}
int main()
{
int i = 0;
/*定义一个环形缓冲区*/
ring pt_ring_buff = fifo_init();
/*向环形缓冲区中写入数据*/
for(i = 0;i<10;i++)
{
ring_buff_insert(pt_ring_buff,i);
}
/*从环形缓冲区中读出数据*/
for(i = 0;i<10;i++)
{
printf("%d ",ring_buff_get(pt_ring_buff));
}
/*销毁一个环形缓冲区*/
ring_buff_destory(pt_ring_buff);
return (1);
}
实现环形队列图示过程
5.如上图所示添加a6时,rear指针发生溢出.我们使用一个小技巧,当rear=6时与数组大小6进行取模, (rear+1) % maxLen,让rear指针回到开始处rear=0,问题来了,我们无法判断数组是否满?因为初始化时front=rear=0, 现在数组满也是front=rear=0
使用第3种方法: 即当(rear+1) % maxLen == front时,判断环形数组满,则无法添加元素
头指针和尾指针指向同一个位置代表当前队列为空,当前环形队列不能将数据插满,如果插满则无法判断队列为空的情况。所以最后一个位置要空出来,不插入值。判定队列满的情况则是用尾指针的下一个指针指向头则说明当前环形队列已满。
在C++中实现环形队列时,可以使用索引或指针来表示读和写的位置,具体取决于你的实现方式和个人偏好。以下是两种常见的方法:
int queue[MAX_SIZE]; // 假设队列的最大大小是MAX_SIZE
int front = 0; // 头部索引
int rear = 0; // 尾部索引
// 入队操作
void enqueue(int item) {
if ((rear + 1) % MAX_SIZE == front) {
// 队列已满
cout << "队列已满,无法入队" << endl;
return;
}
queue[rear] = item;
rear = (rear + 1) % MAX_SIZE;
}
// 出队操作
int dequeue() {
if (front == rear) {
// 队列为空
cout << "队列为空,无法出队" << endl;
return -1; // 返回一个特定的错误值或抛出异常
}
int item = queue[front];
front = (front + 1) % MAX_SIZE;
return item;
}
int queue[MAX_SIZE]; // 假设队列的最大大小是MAX_SIZE
int *front = queue; // 头部指针
int *rear = queue; // 尾部指针
// 入队操作
void enqueue(int item) {
if ((rear + 1) % MAX_SIZE == front) {
// 队列已满
cout << "队列已满,无法入队" << endl;
return;
}
*rear = item;
rear = (rear + 1) % MAX_SIZE;
}
// 出队操作
int dequeue() {
if (front == rear) {
// 队列为空
cout << "队列为空,无法出队" << endl;
return -1; // 返回一个特定的错误值或抛出异常
}
int item = *front;
front = (front + 1) % MAX_SIZE;
return item;
}
无论你选择使用索引还是指针,都可以实现一个有效的环形队列。选择哪种方式取决于你的偏好和实际需求。指针的方法在某些情况下可能更直观,因为你可以像操作普通数组一样操作指针,而无需进行索引运算。但索引方法也是常见的,因为它们更容易理解和实现。
代码
#include
const int MAX_SIZE = 10; // 假设队列的最大大小是10
class CircularQueue {
private:
int queue[MAX_SIZE]; // 队列数组
int front; // 头部索引
int rear; // 尾部索引
public:
CircularQueue() {
front = -1;
rear = -1;
}
// 判断队列是否为空
bool isEmpty() {
return front == -1 && rear == -1;
}
// 判断队列是否已满
bool isFull() {
return (rear + 1) % MAX_SIZE == front;
}
// 入队操作
void enqueue(int item) {
if (isFull()) {
std::cout << "队列已满,无法入队" << std::endl;
return;
}
if (isEmpty()) {
front = rear = 0;
} else {
rear = (rear + 1) % MAX_SIZE;
}
queue[rear] = item;
}
// 出队操作
int dequeue() {
if (isEmpty()) {
std::cout << "队列为空,无法出队" << std::endl;
return -1; // 返回一个特定的错误值或抛出异常
}
int item = queue[front];
if (front == rear) {
front = rear = -1; // 队列中只有一个元素时的特殊情况
} else {
front = (front + 1) % MAX_SIZE;
}
return item;
}
};
int main() {
CircularQueue q;
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
std::cout << "Dequeued: " << q.dequeue() << std::endl;
std::cout << "Dequeued: " << q.dequeue() << std::endl;
std::cout << "Dequeued: " << q.dequeue() << std::endl;
q.enqueue(4);
q.enqueue(5);
std::cout << "Dequeued: " << q.dequeue() << std::endl;
std::cout << "Dequeued: " << q.dequeue() << std::endl;
return 0;
}
运行
Dequeued: 1
Dequeued: 2
Dequeued: 3
Dequeued: 4
Dequeued: 5
代码
#include
#include
class CircularQueue {
private:
std::vector<int> queue;
int front;
int rear;
int maxSize;
public:
CircularQueue(int size) : maxSize(size) {
queue.resize(size);
front = -1;
rear = -1;
}
bool isEmpty() {
return front == -1 && rear == -1;
}
bool isFull() {
return (rear + 1) % maxSize == front;
}
void enqueue(int item) {
if (isFull()) {
std::cout << "队列已满,无法入队" << std::endl;
return;
}
if (isEmpty()) {
front = rear = 0;
} else {
rear = (rear + 1) % maxSize;
}
queue[rear] = item;
}
int dequeue() {
if (isEmpty()) {
std::cout << "队列为空,无法出队" << std::endl;
return -1; // 返回一个特定的错误值或抛出异常
}
int item = queue[front];
if (front == rear) {
front = rear = -1;
} else {
front = (front + 1) % maxSize;
}
return item;
}
};
int main() {
CircularQueue q(10);
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
std::cout << "Dequeued: " << q.dequeue() << std::endl;
std::cout << "Dequeued: " << q.dequeue() << std::endl;
std::cout << "Dequeued: " << q.dequeue() << std::endl;
q.enqueue(4);
q.enqueue(5);
std::cout << "Dequeued: " << q.dequeue() << std::endl;
std::cout << "Dequeued: " << q.dequeue() << std::endl;
return 0;
}
运行
Dequeued: 1
Dequeued: 2
Dequeued: 3
Dequeued: 4
Dequeued: 5
代码
#include
#include
#include
#include
#include
const int bufferSize = 5; // 缓冲区大小
class CircularQueue {
public:
CircularQueue() : buffer(bufferSize), front(0), rear(0), count(0) {}
// 生产者线程使用的enqueue函数,将数据添加到队列
void enqueue(int item) {
std::unique_lock<std::mutex> lock(mutex);
// 检查队列是否已满
if (count < bufferSize) {
buffer[rear] = item;
rear = (rear + 1) % bufferSize;
count++;
std::cout << "Produced: " << item << std::endl;
// 通知等待中的消费者线程有新数据可用
cv.notify_all();
}
}
// 消费者线程使用的dequeue函数,从队列中取出数据
int dequeue() {
std::unique_lock<std::mutex> lock(mutex);
// 如果队列为空,等待生产者生产数据
while (count == 0) {
cv.wait(lock);
}
// 从队列中取出数据
int item = buffer[front];
front = (front + 1) % bufferSize;
count--;
std::cout << "Consumed: " << item << std::endl;
return item;
}
private:
std::vector<int> buffer; // 缓冲区,用于存储数据
int front; // 队列前部索引
int rear; // 队列后部索引
int count; // 当前队列中的元素数量
std::mutex mutex; // 用于线程同步的互斥锁
std::condition_variable cv; // 条件变量,用于线程等待和通知
};
// 生产者线程函数,负责向队列中添加数据
void producer(CircularQueue &queue) {
for (int i = 1; i <= 10; ++i) {
queue.enqueue(i);
// 模拟生产耗时
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
// 消费者线程函数,负责从队列中取出数据
void consumer(CircularQueue &queue) {
for (int i = 0; i < 10; ++i) {
int item = queue.dequeue();
// 模拟消费耗时
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
}
int main() {
CircularQueue queue;
// 创建生产者线程和消费者线程
std::thread producerThread(producer, std::ref(queue));
std::thread consumerThread(consumer, std::ref(queue));
// 等待线程结束
producerThread.join();
consumerThread.join();
return 0;
}