一.基本原理
我们应该都去过银行、医院等单位办过事情,每次去了后需要取号,叫号轮到自己的时候才会去办理业务,因此极大的提高了工作效率,缩短了等候时间,其实这其中的原理便是一个简单的循环队列实现的。
1.队列的定义
队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表。
2.循环队列
在用顺序表实现队列时,往往会因为表头指针的不断后移造成队头空间的不可利用(链式队列不需要考虑该问题),为充分利用向量空间,克服"假上溢"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。即:循环队列中进行出队、入队操作时,头尾指针仍要加1,朝前移动。只不过当头尾指针指向向量上界(QueueSize-1)时,其加1操作的结果是指向向量的下界0。
原理示意:
3.循环队列入队的算法
(1)把值存在rear所在的位置;
(2)rear=(rear+1)%maxsize ,其中maxsize代表数组的长度;
4.循环队列出队的算法
(1)先保存出队的值;
(2)front=(front+1)%maxsize ,其中maxsize代表数组的长度;
5.如何判断循环队列是否为空
if(front==rear)
队列空;
else
队列不空;
6.如何判断循环队列是否为满
一是增加一个参数,用来记录数组中当前元素的个数;第二个办法是,少用一个存储空间,也就是数组的最后一个存数空间不用,当(rear+1)%maxsiz=front时,队列满;
二.叫号系统实现过程
1.结构定义
int count=0; //全局序号标记量
typedef struct{
int client_num[maxsize]; //当前位置有人等候时插入序号,0为空闲
int front,rear;
}seqQueue;
2.基本初始化、入队、出队函数
seqQueue *inital_queue() //初始化队列
{
seqQueue *p;
p=(seqQueue *)malloc(sizeof(seqQueue));
for(int i=0;i<maxsize;i++)
{
p->client_num[i]=0;
}
p->front=p->rear=-1;
return p;
}
int inQueue(seqQueue *p) //入队
{
if((p->rear+1)%maxsize==p->front) //判断队满,预留一个空元素
{
printf("The queue was filled!");
return 0;
}
p->rear=(p->rear+1)%maxsize;
p->client_num[p->rear]=count; //设立排队序号
return 0;
}
int outQueue(seqQueue *p) //出队
{
int temp;
if(p->front==-1&&p->rear==-1||p->front==p->rear) //判断队空
{
printf("The queue is empty!\n");
return 0;
}
temp=p->front;
p->client_num[p->front]=0;
p->front++;
return temp;
}
3.主函数
int main_menu(seqQueue *p) //菜单选项
{
int m=0;
char select;
while(1)
{
printf("\t\t\t1.取号\n");
printf("\t\t\t2.叫号\n");
printf("\t\t\t0.退出\n");
select=getch();
switch(select)
{
case '1':count++;inQueue(p);system("cls");printf("\t\t\t取号成功!您的序号为%d,即将返回主页面\n",count);Sleep(3000);system("cls");break;
case '2':system("cls");outQueue(p);printf("\t\t\t%d号请办理业务即将返回主页面\n",p->client_num[p->front]);Sleep(3000);system("cls");break;
case '0':exit(0);break;
default:break;
}
}
return 0;
}
int main()
{
int i=0,j=0;
seqQueue *p;
p=inital_queue();
main_menu(p);
return 0;
}
三.运行结果