//该种算法的核心是在头尾指针相同时,上一步操作是什么
//如果上一步操作是出队,此时头尾指针相同,则是空队列 
//相反,如果上一步操作是入队,此时便是满队列 
//所以只需要在原来的出队入队的算法尾部加一个tag的赋值即可
//并且在判断队列空或者满的时候同时判断tag的值

//这里我假设队列空 tag 为 0
//队列满 tag 为 1
//并且 tag 初始化为 0 因为队列还未进行任何操作时,肯定是空队列 

#define MAX 100  //最大队列长度
typedef struct{
	int *base;  //初始化的动态分配存储空间
	int front;
	int rear;   //尾指针 
}SqQuene;

int tag = 0;

//入队操作 
int EnQuene(SqQuene &Q,char e){  //假设队列元素 
	//插入元素 e  将 e 入队
	//先判断队列为空还是满
	if(Q.front==(Q.rear+1)%MAX && tag == 1){
		return ERROR; //队列满 
	}else{
		Q.base[Q.rear]==e;
		Q.rear = (Q.rear+1)%MAX;
		tag=1;  //将元素入队则令tag=1 
		//为下一步判断队空队满做准备 
		return OK;
	}
} 

//出队操作 
int DeQuene(SqQuene &Q,char &e){  //假设队列元素 
	//插入元素 e  将 e 入队
	//先判断队列为空还是满
	if(Q.front==(Q.rear+1)%MAX && tag == 0){
		return ERROR; //队列空 
	}else{
		e=Q.base[Q.front];
		Q.front = (Q.front+1)%MAX;
		tag=0;  //将元素出队则令tag=0 
		//为下一步判断队空队满做准备 
		return OK;
	}
} 

设标志tag节省存储空间,但是运行时间较长,不设tag则正好相反。 如果当循环队列容量较小而队列中每个元素占内存较多时就用设置标志tag的办法; 如果当循环队列容量较大而队列中每个元素占内存较少时就用少用一个元素空间的办法; 这样使用可以使时间和空间的最优化。