球钟问题

news/2025/2/2 23:38:06/文章来源:https://www.cnblogs.com/yangyang13/p/18697245

球钟问题

1. 问题背景

​ 球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器和小时指示器。

举例:若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32

2. 工作原理

​ 每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。

​ 按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。

​ 当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该球钟表示时间的范围为0:00到11:59.

3. 问题

现设初始时球队列的球数为27,球钟的三个指示器初态均为空,问,经过多久,球队列才能恢复到原来的顺序?

4. 求解和实现

4.1 求解思路:

1. 球队列的功能是实现 <= 27 个球的头出,尾部插入: 用链式队列实现。(顺序队列要跑循环,相对没那么方便)
2. 三个指示器的功能是存球,然后反顺序输出,固定存储大小:用顺序栈实现。
3. 计时逻辑是指示器栈满向前+1,然后清空当前栈。
4. 问题判断是否恢复原来顺序。初始化队列为有序队列1到27,后续判断队列是否满足从小到大排序即可。
5. 可复用代码:linkqueue.c/h 链队列, sqstack.c/h 顺序栈。

4.2 实现代码:

main.c

#include <stdio.h>
#include "sqstack.h"
#include "linkqueue.h"int check(linkqueue q);int main()
{// 1. 创建球队列和三个指示器栈和计时变量timeint time = 0;linkqueue ballqueue = linkqueue_create();if (ballqueue == NULL){printf("创建球队列失败!\n");return	-1;}sqstack minstack = sqstack_create(4);sqstack fivestack = sqstack_create(11);sqstack hourstack = sqstack_create(11);if (minstack == NULL || fivestack == NULL || hourstack == NULL){printf("创建指示器栈失败!\n");return	-1;}// 2. 初始球队列for (size_t i = 1; i <= 27; i++){linkqueue_enqueue(ballqueue, i);}linkqueue_show(ballqueue);printf("球队列初始化完成!\n");// 3. 开始计时,并调用检查函数判断是否恢复原始球队列while (1){time++;if (!sqstack_full(minstack)){sqstack_push(minstack, linkqueue_dequeue(ballqueue));}else{while (!sqstack_empty(minstack)){linkqueue_enqueue(ballqueue, sqstack_pop(minstack));}if	(!sqstack_full(fivestack)){sqstack_push(fivestack, linkqueue_dequeue(ballqueue));}else{while (!sqstack_empty(fivestack)){linkqueue_enqueue(ballqueue, sqstack_pop(fivestack));}if (!sqstack_full(hourstack)){sqstack_push(hourstack, linkqueue_dequeue(ballqueue));}else{while (!sqstack_empty(hourstack)){linkqueue_enqueue(ballqueue, sqstack_pop(hourstack));}linkqueue_enqueue(ballqueue, linkqueue_dequeue(ballqueue));if (check(ballqueue) == 1){break;}}}}}printf("***********\n");printf("检查球队列恢复是否原始状态!\n");linkqueue_show(ballqueue);printf("用时:%d\n",time);linkqueue_free(&ballqueue);sqstack_free(&minstack);sqstack_free(&fivestack);return 0;
}int	check(linkqueue q)
{queuenode tem = q->front->next;int i = 0;while (tem->next != NULL){if (tem->data < tem->next->data){tem = tem->next;i++;}else{return 0;}}return 1;
}

linkqueue.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkqueue.h"/*** @name 	linkqueue_create()* @brief	创建链式队列* @param  NULL* @retval q 队列地址*/
linkqueue linkqueue_create()
{// 1. 申请队列头尾指针内存和队列节点内存linkqueue p = (linkqueue)malloc(sizeof(linkqueue_struct));if (p ==  NULL){printf("linkqueue malloc error\n");return NULL;}queuenode newnode = (queuenode)malloc(sizeof(queuenode_struct));if (newnode == NULL){printf("linknode malloc error\n");free(p);return NULL;}// 2. 初始化队列头尾指针和队列节点p->front = p->rear = newnode;newnode->next = NULL;newnode->data = -1;return p;
}/*** @name 	linkqueue_create()* @brief	p判断链式队列是否为空* @param  q 队列地址* @retval 0 队列不为空,1 队列为空,-1 队列不存在*/
int linkqueue_empty(linkqueue q)
{// 1. 判断队列是否存在if (q == NULL){printf("linkqueue is invalid\n");return -1;}// 2. 判断队列是否为空return q->front == q->rear ? 1 : 0;
}/*** @name 	linkqueue_enqueue()* @brief	入队* @param  q 队列地址* @retval 0 入队成功,-1 入队失败*/
int linkqueue_enqueue(linkqueue q, data_t x)
{// queuenode tem;// 1. 判断队列是否存在if (q == NULL){printf("linkqueue is invalid\n");return -1;}// 2. 申请队列节点内存queuenode newnode = (queuenode)malloc(sizeof(queuenode_struct));if (newnode == NULL){printf("queuenode malloc error\n");return -1;}newnode->data = x;newnode->next = NULL;// 3. 将新节点插入到队列尾结点之后,并尾指针指向新节点// tem = q->front;// while (tem->next != NULL)// {//     tem = tem->next;// }// tem->next = newnode;q->rear->next = newnode;q->rear = newnode;return 0;
}
/*** @name 	linkqueue_dequeue()* @brief	出队* @param  q 队列地址* @retval 出队元素*/
data_t linkqueue_dequeue(linkqueue q)
{// 1. 判断队列是否存在if (q == NULL){printf("linkqueue is invalid\n");return -1;}// 2. 判断队列是否为空if (q->front == q->rear){printf("linkqueue is empty\n");return -1; }// 3. 出队操作,释放队头结点,并头指针指向头结点下一个结点queuenode tem = q->front->next;data_t x = tem->data;q->front->next = tem->next;if (q->rear == tem){q->rear = q->front;}free(tem);return x;
}
/*** @name 	linkqueue_show()* @brief	遍历队列,输出队列元素* @param  q 队列地址* @retval -1 遍历失败,0 遍历成功*/
int linkqueue_show(linkqueue q)
{// 1. 判断队列是否存在以及队列是否为空if (q == NULL){printf("linkqueue is invalid\n");return -1;}if (q->front == q->rear){printf("linkqueue is empty\n");return -1; }// 2. 遍历队列,输出队列元素queuenode tem = q->front->next;while (tem != NULL){printf("%d \n", tem->data);tem = tem->next;}return 0;
}/*** @name 	linkqueue_free()* @brief	遍历队列,输出队列元素* @param  q 队列地址* @retval -1 释放失败,0 释放成功*/
int linkqueue_free(linkqueue *q)
{// 1. 判断队列是否存在if (*q == NULL){printf("linkqueue is invalid\n");return -1;}// 2. 释放队列queuenode tem = (*q)->front;while (tem != NULL){queuenode next = tem->next;free(tem);tem = next;}free(*q);*q = NULL;return 0;
}

linkqueue.h

typedef int data_t;typedef struct node_t
{data_t data;                 // 数据域struct node_t *next;        // 指针域
} queuenode_struct, *queuenode; // 队列结点结构体类型定义typedef struct
{queuenode front, rear;
} linkqueue_struct,*linkqueue;  // 队列结构体类型定义linkqueue linkqueue_create();                     // 创建队列
int linkqueue_empty(linkqueue q);                 // 判断队列是否为空
int linkqueue_enqueue(linkqueue q, data_t x);     // 入队
data_t linkqueue_dequeue(linkqueue q);            // 出队
int linkqueue_show(linkqueue q);                  // 遍历队列
int linkqueue_free(linkqueue *q);                 // 释放队列

sqstack.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for memset
#include "sqstack.h"/*** @name 	sqstack_create()* @brief	创建顺序栈* @param  length	栈长* @retval 栈地址*/
sqstack sqstack_create(int length)
{sqstack s;// 1. 检查栈长参数是否合理if (length < 0){printf("length is invalid\n");return NULL;}// 2. 申请栈空间,先申请栈结构体,然后申请data空间if ((s = (sqstack)malloc(sizeof(sqstack_struct))) == NULL){printf("malloc sqstack failed\n");return NULL;}if ((s->data = (data_t *)malloc(length*sizeof(data_t))) == NULL){printf("malloc sqstack->data failed\n");free(s);return NULL;}// 3. 初始化栈memset(s->data, 0, length*sizeof(data_t));s->maxlen = length;s->top = -1;return s; 
}/*** @name 	sqstack_push()* @brief	顺序栈入栈* @param  s 栈地址,x 入栈元素* @retval 0 入栈成功,-1 入栈失败*/
int sqstack_push(sqstack s, data_t x)
{// 1. 检查栈是否存在以及栈是否满if (s == NULL){printf("sqstack is invalid\n");return -1;}if (s->top == s->maxlen - 1){printf("sqstack is full\n");return -1;}// 2. 入栈s->top++;s->data[s->top] = x;return 0;
}/*** @name 	sqstack_empty()* @brief	顺序栈判断是否为空* @param  s 栈地址* @retval 1 栈为空,0 栈不为空*/
int sqstack_empty(sqstack s)
{// 1. 检查栈是否存在if (s == NULL){printf("sqstack is invalid\n");return -1;}// 2. 通过栈顶判断栈是否为空return(s->top == -1 ? 1 : 0);    
}/*** @name 	sqstack_full()* @brief	顺序栈判断是否满* @param  s 栈地址* @retval 1 栈为满,0 栈不满*/
int sqstack_full(sqstack s)
{// 1. 检查栈是否存在if (s == NULL){printf("sqstack is invalid\n");return -1;}// 2. 通过栈顶判断栈是否为满return(s->top == s->maxlen - 1 ? 1 : 0);
}/*** @name 	sqstack_pop()* @brief	顺序栈出栈* @param  s 栈地址* @retval 出栈元素*/
data_t sqstack_pop(sqstack s)
{// 1. 检查栈是否存在if (s == NULL){printf("sqstack is invalid\n");}// 2. 出栈s->top--;return s->data[s->top+1];
}/*** @name 	sqstack_top()* @brief	顺序栈获取栈顶元素* @param  s 栈地址* @retval 出栈元素*/
data_t sqstack_top(sqstack s)
{// 1. 检查栈是否存在if (s == NULL){printf("sqstack is invalid\n");}// 2. 返回栈顶元素return s->data[s->top];
}/*** @name 	sqstack_clear()* @brief	顺序栈清空* @param  s 栈地址* @retval 0 清空成功,-1 清空失败*/
int sqstack_clear(sqstack s)  
{// 1. 检查栈是否存在if (s == NULL){printf("sqstack is invalid\n");return -1;}// 2. 清空栈。直接将栈顶置为-1,后续的入栈操作会覆盖原来的值。s->top = -1;return 0;
}/*** @name 	sqstack_free()* @brief	顺序栈出栈* @param  s 栈地址* @retval 0 释放成功,-1 释放失败*/
int sqstack_free(sqstack *s)
{if (*s == NULL){printf("sqstack is invalid\n");return -1;}if ((*s)->data != NULL){free((*s)->data);}free(*s);*s = NULL;return 0;
}

sqstack.h

typedef int data_t;     // 定义数据类型  typedef struct 
{data_t *data;int maxlen;           // 栈最大长度int top;             // 栈顶-1标准栈为空
} sqstack_struct,*sqstack;sqstack sqstack_create(int length);       // 创建一个长度为length的栈,返回值为栈的指针
int sqstack_push(sqstack s, data_t x);     // 元素x入栈,返回值为 0表示成功,-1表示失败
int sqstack_empty(sqstack s);              // 判断栈是否为空,返回值为 1表示空,0表示非空
int sqstack_full(sqstack s);               // 判断栈是否为满,返回值为 1表示满,0表示非满
data_t sqstack_pop(sqstack s);             // 栈顶元素出栈,返回值为栈顶元素
data_t sqstack_top(sqstack s);             // 返回栈顶元素,栈顶元素不变
int sqstack_clear(sqstack s);              // 清空栈,返回值为 0表示成功,-1表示失败
int sqstack_free(sqstack *s);               // 释放栈,返回值为 0表示成功,-1表示失败

5 结果:

image-20250202233400654

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/878143.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地部署deepseek

前言 如果你电脑配置不错,且期望不受网络限制也可以流畅使用deepseek,那就本地部署deepseek试试吧。下载并安装Ollama Ollama是一个开源的 LLM(大型语言模型)服务工具(就是大模型运行工具),用于简化在本地运行大语言模型,降低使用大语言模型的门槛,使得大模型的开发者…

【邮件安全】近期常见的钓鱼邮件(202411期)

本期主要分享自2024年11月至今几种典型的钓鱼邮件样本。希望通过这种分享,可以帮助广大用户提高警惕性,增强识别与防范钓鱼邮件的能力。 邮箱账户异常类 以下图为例,该钓鱼邮件伪造用户账户出现异常登录情况,引导用户点击“认证账户”按钮进入钓鱼页面。 下图是一封伪造用户…

AI医院:大语言模型在多智能体医疗交互模拟器中的表现如何?

近年来,人工智能(AI)技术,尤其是大语言模型(LLMs),在医学领域取得了显著进展。这些模型在静态医疗问答任务中表现优异,甚至在某些情况下能够媲美人类专家。然而,医学诊断并非单一静态的任务,而是一个动态、复杂的过程,涉及多轮互动和信息收集。 为了更全面地评估LLM…

万字综述|一文掌握大语言模型在生物信息学中的应用

随着大语言模型(LLMs)技术的飞速发展,其在自然语言处理(NLP)领域的成功应用逐渐扩展到了生物信息学领域。生物信息学作为一个跨学科的领域,涉及基因组学、蛋白质组学、药物发现等多个方向,LLMs的引入为这些领域带来了新的研究工具和方法。 2025年1月,佐治亚大学Tianmin…

自主做前端页面小工程07

通过使用elementui和js部分代码实现 其重点在于导航栏与弹窗和数据的回显与数据只可预览,基本完成 这是补发昨天学习记录

自主做前端小工程08

今天学习记录,完成部门经理页面,主要是分vue中的变量,创建了更多对话框页面和表单

【邮件安全】近期常见的钓鱼邮件(202412期)

# 钓鱼邮件样本 本期主要分享自2024年12月至今几种典型的钓鱼邮件样本。年关将至,大家要擦亮眼睛,谨防受骗! 带附件类钓鱼上图是一封带有html附件的钓鱼邮件,html附件中包含钓鱼页面。一旦用户打开html文件,可能会非法收集用户个人信息或引导用户输入账号密码等敏感信息。…

CTF-web过年加更

一、菜狗杯的无一幸免看代码可以发现$arr[]=1(在数组中追加一个数且赋值为1,永久为真),想要饶过它就需要让数组溢出(最大int数) int范围为32位:2的31次方-1=2147483647;64位:2的63次方-1=9,223,372,036,854,775,807 在顶部传入参数0=(以上2个看情况选)即可拿到flag二…

python 项目工程化开发

虚拟环境工具 安装poetry pip install -U peotry上述方式不行时 (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python加入环境变量初始化项目 安装cookiecutter pip install -U cookiecutter初始化项目 cd workspace cookiecutter …

Java-GUI编程-五子棋游戏

java-gui编程-五子棋小游戏 文件目录如下: 棋盘背景图如下: 运行效果如下: FiveChess类代码: package com.gui.fivechess;public class FiveChess { //主类,运行该类即可启动游戏 public static void main(String[] args) { FiveChessFrame ff = new FiveChe…

【模拟电子技术】18-多级放大电路的构成与动态分析

【模拟电子技术】18-多级放大电路的构成与动态分析 单极放大电路往往不能满足我们的需求,比如有一个电压型的信号源,其内阻还不能忽略,输出端要求输出稳定的电压,要求设计尽可能放大的放大电路。 即Ri大,R0小例如这样就可以实现,接下来看直接耦合放大电路的“进化”图(a…

AvaloniaUI 的甘特图组件.

https://github.com/xiejiang2014/XieJiang.Gantt.Avalonia Gantt chart component for AvaloniaUI(UNDER CONSTRUCTION).