问题描述: 球钟是利用球的移动来记录时间的装置
它有三个可以容纳若干个球的容器:分钟指示器,五分钟指示器,小时指示器。
若分钟指示器中有2个球,5分钟指示器中有3个球,小时指示器中有4个球,则时间为4:17。
每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。在放进去第五个球的时候,分钟指示器内的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。
队列中球数为27:小时容器11个 + 5分钟容器11个 + 1分钟容器4个 = 26个,第27个球的作用很特殊,作用是把这26个清空,实现11:59到00:00的转变。
#include <stdio.h>
#include "linkqueue.h"
#include "sqstack.h"
int check(linkqueue * lq);
int main(int argc, const char *argv[])
{
linkqueue *lq; // 描述链式队列的结构体,里面有front,rear
sqstack *s_hour, *s_five, *s_min; // 定义了3个结构体指针,指向顺序栈对象
int value;
int i, min = 0;
if ((lq = queue_create()) == NULL) { // 创建链式队列
return -1;
}
for (i = 1; i <= 27; i++) { // 将27个球入队
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++; // 这里记录次数,因为题目问的就是min有多少次
if (!queue_empty(lq)) { // 如果队列还有数
value = dequeue(lq); // 出队一个数给value,利用value将这个数送入栈
if (!stack_full(s_min)) {
stack_push(s_min, value); // 后面代码不再执行
} else { // 此时value中的球还没入栈,else执行,说明min栈满了,这个球会在后面给到5min栈
while (!stack_empty(s_min)) {
enqueue(lq, stack_pop(s_min)); //*将min栈出栈 同时入队到队列,直到栈空为止
}
if (!stack_full(s_five)) { // 这里注意括号,这个if是在else里面的,即此时min栈满了,但又被清空了
stack_push(s_five, value); // min栈满了,清空min栈后,5min栈入栈一元素,后面代码不再执行
} else { // else执行,说明min栈、5min栈都满了
while (!stack_empty(s_five)) { // while循环,开始清理5min栈
enqueue(lq, stack_pop(s_five)); // 出栈后入队
}
if (!stack_full(s_hour)) {
stack_push(s_hour, value); // 之前的5min栈满了,小时栈自然要push一个值,后面不再执行
} else { // 此时的value是第27个球,else执行,说明min栈、5min栈、小时栈都满了
while (!stack_empty(s_hour)) {
enqueue(lq, stack_pop(s_hour)); // 清空小时栈后入队
}
enqueue(lq, value); // 这个第27个球,不会入栈,在外边溜达一圈后直接归队
//上面语句执行完后,27个球全部归队,时间置为00:00
if (check(lq) == 1) {
break; // 这个break跳出的是while(1)循环,其他while循环均不在break外层
}
}
}
}
}
} // while(1)的回括号
printf("total:%d\n", min);
printf("dequeue:");
while (!queue_empty(lq))
printf("%d ", dequeue(lq));
puts("");
return 0;
} // main的回括号
// 检查传入的链式队列,是否为升序,若是返回1,不是返回0
int check(linkqueue * lq) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
p = lq->front->next; // p指向队头
while (p && p->next) { // 队头和队头后面一个元素均非空时
if (p->data < p->next->data) {
p = p->next;
} else {
return 0;
}
}
return 1;
}
Stack: https://blog.csdn.net/small0dragon/article/details/136541301
Queue: https://blog.csdn.net/small0dragon/article/details/136541324