1、球钟问题
球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器,若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32
2、工作原理
每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。
当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。
按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球
当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该球钟表示时间的范围是从0:00到11:59。
现设初始时球队列的球数为27,球钟的三个指示器初态均为空。问,要经过多久,球队列才能回复到原来的顺序?
3、程序
int main(int argc, const char *argv[])
{
linkqueue *lq;
sqstack *s_hour, *s_five, *s_min;
int value;
int i, min = 0;
if ((lq = queue_create()) == NULL) {
return -1;
}
for (i = 1; i <= 27; i++) {
enqueue(lq, i);
}
if ((s_hour = stack_create(11)) == NULL) {
return -1;
}
if ((s_five = stack_create(11)) == NULL) {
return -1;
}
if ((s_min = stack_create(4)) == NULL) {
return -1;
}
while (1) {
min++;
if (!queue_empty(lq)) {
value = dequeue(lq);
if (!stack_full(s_min)) {
stack_push(s_min, value);
} else {
while (!stack_empty(s_min)) {
enqueue(lq, stack_pop(s_min));
}
if (!stack_full(s_five)) {
stack_push(s_five, value);
} else {
while (!stack_empty(s_five)) {
enqueue(lq, stack_pop(s_five));
}
if (!stack_full(s_hour)) {
stack_push(s_hour, value);
} else {
while (!stack_empty(s_hour)) {
enqueue(lq, stack_pop(s_hour));
}
enqueue(lq, value);
//0:0
if (check(lq) == 1) {
break;
}
}
}
}
}
}
printf("total:%d\n", min);
printf("dequeue:");
while (!queue_empty(lq))
printf("%d ", dequeue(lq));
puts("");
return 0;
}
int check(linkqueue * lq) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
p = lq->front->next;
while (p && p->next) {
if (p->data < p->next->data) {
p = p->next;
} else {
return 0;
}
}
return 1;
}
注:程序中check函数是为了,退出循环时,队列中的元素依然是123…27的顺序,这需要循环很多次,不只一个0:00-11:59。min变量每循环一次就+1,表示增加一分钟。程序运行结果是33120,即队列从开始计时,到队列恢复原来排序需要33120分钟,即46个0:00-11:59周期。
程序中,选用的是链式队列和顺序栈。