3.球钟问题

3 篇文章 0 订阅

问题描述: 球钟是利用球的移动来记录时间的装置

它有三个可以容纳若干个球的容器:分钟指示器,五分钟指示器,小时指示器。

若分钟指示器中有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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值