循环队列是一种常见的队列实现方式,各个数据元素依次存储,并设置两个指针,分别指向队头和队尾,在插入和删除数据时,队头指针和队尾指针会循环使用存储空间。应用队列可以解决报数问题。
报数问题:设有n个人站成一排,从左向右的编号分别为1~n, 现在从左向右报数“1,2,1,2,1,2….”,数到”1”的人出列,数到”2”的人站到队伍最右边。报数过程反复进行,直到n个人都出列为止。
分析:可以创建一个队列存储各个数据。左边相当于队头,右边相当于队尾。左边的人报数相当于从队列中取出队头元素并删除队头元素。站到队伍的最右边相当于在队尾插入一个数据。为实现1,2,1,2,1,2….报数,可以设置一个计数器变量count,count每次加1,count%2交替等于1和0,count%2等于1相当于报数1,count%2等于0相当于报数2。
此程序在VC++6.0 和 Dev-C++下编译通过。
#include "stdio.h"
#include "stdlib.h"
#define MAXQSIZE 100 //最大队列长度
typedef struct
{
int *base; // 动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素 的下一个位置
} SqQueue;
int InitQueue (SqQueue &Q)
{
// 构造一个空队列Q
Q.base = (int *) malloc(MAXQSIZE*sizeof(int));
if(!Q.base)
exit (-2); // 存储分配失败
Q.front = Q.rear = 0;
return 1;
}
void DestroyQueue(SqQueue &Q)
{ //销毁队列
free(Q.base);
Q.base=NULL;
Q.front=0;
Q.rear=0;
}
int QueueEmpty(SqQueue Q)
{ //判断队列是否为空队列
if(Q.front==Q.rear)
return 1;
else
return 0;
}
int EnQueue(SqQueue &Q, int e)
{ /* 插入元素e为Q的新的队尾元素 */
if((Q.rear+1)%MAXQSIZE==Q.front)
return 0;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE;
return 1;
}
int DeQueue(SqQueue &Q, int &e)
{ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回1;否则返回0 */
if(Q.front==Q.rear) /* 队列空 */
return 0;
e=Q.base[Q.front];
Q.front=(Q.front+1)%MAXQSIZE;
return 1;
}
void baoshu(int n)
{
SqQueue Q;
int i,count=1,e;
InitQueue(Q);
for(i=1;i<=n;i++)
EnQueue(Q, i);
while(!QueueEmpty(Q))
{
DeQueue(Q,e);
if(count%2==1)
printf("%d ",e);
else
EnQueue(Q,e);
count++;
}
printf("\n");
DestroyQueue(Q);
}
int main()
{
int n;
printf("请输入人员数量:");
scanf("%d",&n);
baoshu(n);
return 0;
}