为了解决顺序队列假溢出的问题,提出了循环队列。使得内存的利用率得到了很大的提升。但是在判断循环队列空和满这两种状态任然存在问题,因为对于一个循环队列,不做任何判空和判满的机制。判空和判满的条件都是:q->rear == q->front。带来的问题就是当出现上述条件时不能区分循环队列到底是空还是满,因此为了解决上述问题。人们提出以下两种方案来解决: (1)牺牲一个位置用作判断的条件
队空:q->rear == q->front 队满:(q->rear 1)% N = q->front,其中N为最大队列容量
(2)设置标志位来区分队空和队满,这样就不需要牺牲空间,使得循环队列的空间得到了最大的利用。缺点是需要做很多的逻辑判断来处理标志位。
队空:q->rear == q->front && q->tag == 0 队满:q->rear == q->front && q->tag == 1 此外,在标志位实现循环队列的机制下,需要几个计数器来统计当前队列中元素的个数,方便处理q->tag。
代码实现:
代码语言:javascript复制#include <iostream>
using namespace std;
#define N 5
typedef struct node {
int data[N];
int rear, front;
bool tag;
}queue;
int cnt = 0;
bool isEmpty(queue *q) {
return q->rear == q->front && q->tag == 0;
}
bool isFull(queue *q) {
return q->rear == q->front && q->tag == 1;
}
void init(queue *q) {
q->rear = q->front = 0;
q->tag = 0;
}
void push(queue *q, int x) {
if (isFull(q)) {
cout << "full" << endl;
return ;
} else{
q->data[q->rear] = x;
q->rear = (q->rear 1) % N;
cnt ;
if (cnt == N) q->tag = 1;
}
}
void pop(queue *q) {
if (isEmpty(q)) {
cout << "empty" << endl;
return;
} else {
cnt --;
if (cnt == 0) q->tag = 0;
q->front = (q->front 1) % N;
}
}
int front(queue *q) {
if (isEmpty(q)) {
cout << "empty" << endl;
return -1;
} else {
int res = q->data[q->front];
q->front = (q->front 1) % N;
cnt --;
if (cnt == 0) q->tag = 0;
return res;
}
}
int main() {
int a[] = {1,2,3,4,5};
int n = sizeof a/sizeof(int);
queue q;
init(&q);
for (int i=0; i<n; i) {
push(&q, a[i]);
}
while (!isEmpty(&q)){
cout << front(&q) << " ";
}
cout << endl;
return 0;
}