14.用标志域表示队空队满状态的循环队列的综合操作(**)
描述
要求循环队列不损失一个空间全部都得到利用,设置一个标志域tag,以0和1来区分当队头与队尾指针相同时队列状态的空和满,试编写与此结构相对应的入队和出队操作。
(1)教材中为区分当队头与队尾指针相同时队列状态的空和满,以牺牲一个空间的代价来实现的,空:Q->front == Q->rear,满:(Q->rear+1)%MAXSIZE == Q->front。
(2)本题不损失一个空间,全部都得到利用,为此如下定义循环队列类型:
Typedef struct
{ QueueElementType element[MAXSIZE];
int front;
int rear;
int tag;
}SeqQueue;
此时,循环队列空和满的条件分别为: Q->front == Q->rear&&tag == 0 和Q->front == Q->rear&&tag == 1
(3)编写入队函数、出队函数。
(4)在主函数中编写菜单(1.入队;2.出队;3.退出),调用上述功能函数。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#define error 0
#define OK 1
#define FALSE -1
#define TRUE 1
#define scanf_s scanf
#define MAXSIZE 10
typedef int SeqQueueElemType;
typedef struct queue{
SeqQueueElemType elem[MAXSIZE];
int front;//头指针
int rear;//尾指针
int tag;//标志域
}SeqQueue; //定义队头
void Initqueue(SeqQueue *bt);
int EnterQueue(SeqQueue *bt,SeqQueueElemType x);
int DeleteQueue(SeqQueue *bt,SeqQueueElemType *x);
int printSeqQueue(SeqQueue *bt,int i);
int main();
void Initqueue(SeqQueue *Q)//循环队列初始化操作
{
Q->front=Q->rear=0; //初始化时,队列的头尾指针都指在下表为0处
Q->tag=0; //taq置0.表示对列为空
}
/*TODO:元素加入到队列
功能描述:如果队头和队尾相等并且tag为1,提示队列已经满printf("操作提示:队已满!");并返回error
不满的情况下,把元素加入到队列elem中,增加队尾值,打印提示元素已加入队列printf("操作提示:%d 已入队!",x);
如果此时队头和队尾相等,则设置tag为1,表示队列已满
参数说明:Q-SeqQueue型的队列指针变量
x-SeqQueueElemType型的待加入到队列的元素
返回值说明:成功返回TRUE 队列已满返回error
*/
int EnterQueue(SeqQueue *Q, SeqQueueElemType x)
{
if(Q->front == Q->rear && Q->tag == 1)
{
printf("操作提示:队已满!");
return error;
}
else
{
Q->elem[Q->rear] = x;
Q->rear = (Q->rear+1) % MAXSIZE;//通过求模运算实现循环
printf("操作提示:%d 已入队!",x);
if(Q->front == Q->rear) //如果此时队头和队尾相等,则设置tag为1,表示队列已满
{
Q->tag = 1;
}
}
}
/*TODO:元素出列
功能描述:如果队头和队尾相等并且tag为0,提示队列已经空了printf("操作提示:队为空!");并返回error
不空的情况下,把头部元素赋值给x,打印提示头部元素已出队列printf("操作提示:%d 已出队!",tmp);增加队头值
如果此时队头和队尾相等,则设置tag为0,表示队列为空
参数说明:Q-SeqQueue型的队列指针变量
x-SeqQueueElemType型的出队元素指针
返回值说明:成功返回TRUE 队列已空返回error
*/
int DeleteQueue(SeqQueue *Q, SeqQueueElemType *x)
{
if(Q->front == Q->rear && Q->tag == 0)
{
printf("操作提示:队为空!");
return error;
}
else
{
*x = Q->elem[Q->front];
Q->front = (Q->front+1) % MAXSIZE;
printf("操作提示:%d 已出队!",*x);
if(Q->front == Q->rear) //如果此时队头和队尾相等,则设置tag为0,表示队列为空
{
Q->tag = 0;
}
}
}
int printSeqQueue(SeqQueue *Q,int count)
{
int n;
if((Q->front==Q->rear)&&(Q->tag==0))
printf("操作提示:队列为空!");
else
{
printf("操作结果:");
for(n=Q->front;count>0;n++)
{
printf("%d ",Q->elem[n]);
count--;
}
}
return TRUE;
}
int main()
{
SeqQueue Q;
int i=1,count=0; //count记录队列中剩余数据
SeqQueueElemType x;
Q.front=Q.rear=0;
Q.tag=0; //在主函数提前置空队列,防止程序异常结束。 tag=0;
while(i)
{
printf("
*****************");
printf("
* menue *");
//printf("
*1 置空队列 *");
printf("
*1 入队 *");
printf("
*2 出队 *");
//printf("
*4 打印队列 *");
printf("
*3 退出 *");
printf("
*****************
");
printf("请选择:");
scanf_s("%d",&i);
switch(i)
{
case 1:
printf("请输入数据:");
scanf_s("%d",&x);
EnterQueue(&Q,x);
count++; //每输入一个数据,数据剩余记录+1
if (count>MAXSIZE) //如果数据超出限制,则限制count为最大值 防止输出溢出
count=MAXSIZE;
break;
case 2:
DeleteQueue(&Q,&x);
count--;//每出列一个数据,队列中剩余数据-1
break;
case 3:
printf("操作提示:再见
");
return 0;
default:
printf("操作提示:选择错误,请重新选择!");
break;
}
}
}