数据结构与算法:球钟问题

博客内容涉及一种名为球钟的时间记录装置,通过球的移动来表示时间。解题思路包括确定表示00:00到12:00所需的最少球数,以及模拟从空指示器状态回到初始状态所需的时间。代码示例展示了使用顺序队列和链式栈实现球钟操作的C语言程序,最后给出了编译和运行方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 题目概述

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

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

若分钟指示器中有2个球,5分钟指示器中有3个球,小时指示器中有4个球,则时间为4:17。

每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。在放进去第五个球的时候,分钟指示器内的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。因此,该球种表示的时间范

2. 解题思路

1、要想表示00:00到12:00最少需要多少个球?

围是从00:00到11:59

想象一下,在11:59的时候,分钟指示器里面有4个球,五分钟指示器有11个球,小时指示器有11个球,则这时三个指示器都为临界状态,共用去26个球,而球钟要求能表示12:00,即可理解为00:00,就是要求能从11:59回到00:00,则还需一个球去触发这个临界状态,类似于多米洛骨牌,这个球依次进入三个指示器,并触发其临界状态,三个指示器里的球依次回到队列,然后最后一个球也回到队列,则最少需要27个球。

2、假设指示器都为空,球队列需要多长时间能回到原来的状态? 即从初始球队列中球的顺序,经过球的循环后球队列中的球再次与初始顺序相同。

这时,要理解,回到原来的状态,并不仅仅是27个球都回到队列就完事了!!而且27个球的顺序要和原来一摸一样。

题中的队列很好理解,队首出队尾进嘛,已经明说了用队列去表示,而三个指示器要求按他们的球放入的相反顺序取出,换句话说,就是后进的先出,先进的后出,就是用三个栈去表示三个指示器。

这里我用的顺序循环队列,然后用了三个链式栈。

3. 代码示例

​顺序队列,链式栈的声明。
#ifndef __DATE_H__
#define __DATE_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 28
typedef int data_t;
typedef struct balls{
    data_t ball[SIZE];
    int top;
    int end;
}ball;

typedef struct one{
    data_t onedata;
    struct one *next;
}one_t;

ball *ball_create();
int ball_is_full(ball *head);
int ball_is_empty(ball *head);
int ball_push(ball *head,data_t data);
data_t ball_pop(ball *head);

one_t *one_create();
int one_is_full(one_t *minute,int x);
int one_is_empty(one_t *minute);
int one_push(one_t *minute,data_t onedata);
data_t one_pop(one_t *minute);
void one_clear(one_t *minute);
void all_destory(one_t *minute60,one_t *minute,one_t *minute5,ball *head);
#endif

函数的定义

#include "date.h"
ball *ball_create()
{
    ball *head = (ball *)malloc(sizeof(ball));
    if(NULL == head)
    {
        printf("head error\n");
        return NULL;
    }
    memset(head,0,sizeof(ball));
    head->top = 0;
    head->end = 0;
    return head;
}
int ball_is_full(ball *head)
{
    return (SIZE == (head->end - head->top));
}
int ball_is_empty(ball *head)
{
    return (head->end == head->top);
}
int ball_push(ball *head,data_t data)
{
    if(ball_is_full(head))
    {
        printf("ball full\n");
        return -1;
    }
    head->ball[head->end%SIZE] = data;
    head->end++;
    return 0;
}
data_t ball_pop(ball *head)
{
    if(ball_is_empty(head))
    {
        printf("ball empty\n");
        return -1;
    }
    data_t data = head->ball[head->top%SIZE];
    head->top++;
    if(head->top == head->end)
    {
        head->top = 0;
        head->end = 0;
    }
    return data;
}



one_t *one_create()
{
    one_t *minute = (one_t *)malloc(sizeof(one_t));
    if(NULL == minute)
    {
        printf("minute error\n");
        return NULL;
    }
    memset(minute,0,sizeof(one_t));
    minute->next = NULL;
    return minute;
}
int one_is_full(one_t *minute,int x)
{
    int count = 0;
    one_t *p = minute->next;
    while(p != NULL)
    {
        count++;
        p = p->next;
    }
    if(x == count)
        return 1;
    return 0;
}
int one_is_empty(one_t *minute)
{
    return (minute->next == NULL);
}
int one_push(one_t *minute,data_t onedata)
{
    one_t *p = (one_t *)malloc(sizeof(one_t));
    p->onedata = onedata;
    p->next = NULL;
    one_t *q = minute;
    p->next = q->next;
    minute->next = p;
    return 0;
}
data_t one_pop(one_t *minute)
{
    if(one_is_empty(minute))
    {
        printf("pop empty\n");
        return -1;
    }
    one_t *p = minute->next;
    one_t *q = p->next;
    data_t data = p->onedata;
    minute->next = q;
    free(p);
    return data;
}
void one_clear(one_t *minute)
{
    one_t *p = minute->next;
    one_t *q = NULL;
    while(p != NULL)
    {
        q = p->next;
        free(p);
        p = q;
    }
    minute->next = NULL;
}
void all_destory(one_t *minute60,one_t *minute,one_t *minute5,ball *head)
{
    free(head);
    free(minute);
    free(minute5);
    free(minute60);
}

 主函数

#include "date.h"
int main(int argc, char *argv[])
{ 
    ball *head = ball_create();
    one_t *minute = one_create();
    one_t *minute5 = one_create();
    one_t *minute60 = one_create();
    int n = 27;
    while(n--)
    {
        ball_push(head,n+1);
    }
    int mom;
    int j,a,z;
    scanf("%d",&mom);
    while(mom--)
    {
        data_t data =ball_pop(head);
        if(one_is_full(minute,4))
        {
            if(one_is_full(minute5,11))
            {
                if(one_is_full(minute60,11))
                {
                    j = a = 11;
                    z = 4;
                    ball_push(head,data);
                    while(z--)
                        ball_push(head,one_pop(minute));
                    while(a--)
                        ball_push(head,one_pop(minute5));
                    while(j--)
                        ball_push(head,one_pop(minute60));
                }
                else
                {
                    a = 11;
                    z = 4;
                    one_push(minute60,data);
                    while(z--)
                        ball_push(head,one_pop(minute));
                    while(a--)
                        ball_push(head,one_pop(minute5));
                }
            }
            else
            {
                z = 4;
                one_push(minute5,data);
                while(z--)
                    ball_push(head,one_pop(minute));
            }
        }
        else
            one_push(minute,data);
    }
    int s=0,m=0,w=0;
    while((minute->next) != NULL)
    {
        minute = minute->next;
        w++;
    }
    while((minute5->next) != NULL)
    {
        minute5 = minute5->next;
        m++;
    }
    while((minute60->next) != NULL)
    {
        minute60 =  minute60->next;
        s++;
    }
    printf("the time is:%02d:%02d\n",s,m*5+w);
    all_destory(minute60,minute,minute5,head);
    return 0;
} 

4. 编译

​gcc *.c -o main -g

如果有问题,可以用gdb调试来查找问题。

5. 运行方法

 ./main

12
the time is:00:12
60
the time is:01:00

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雨的路口

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值