栈和队列应用之球鈡问题

一、栈和队列的应用之球鈡问题原理

球钟问题
球钟问题是一个通过球的移动来记录时间的装置问题,其原理与栈和队列的操作特性密切相关。

问题描述
它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。
若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。

工作原理
每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。

当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。

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

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

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

图片来源于网络

二、栈和队列的应用之球鈡问题实现

代码下载链接:git clone https://gitee.com/flying-wolf-loves-learning/data-structure.git

#include <stdio.h>
#include "linkqueue.h"  // 包含队列的头文件
#include "sqstack.h"    // 包含栈的头文件

int check(linkqueue * lq);  // 声明函数check,用于检查队列是否按顺序排列

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){  // 创建队列,若失败则返回-1
        return -1;
    }

    for(i = 1; i <= 27; i++){   // 初始化队列,模拟时钟的27个时间点
        enqueue(lq, i);
    }

    if((s_hour = stack_create(11)) == NULL){  // 创建大小为11的小时栈
        return -1;
    }

    if((s_five = stack_create(11)) == NULL){  // 创建大小为11的五分钟栈
        return -1;
    }

    if((s_min = stack_create(4)) == NULL){    // 创建大小为4的分钟栈
        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){   // 若队列中的时间点按顺序排列,则返回1
            p = p->next;
        } 
        else{
            return 0;   // 若不按顺序排列,则返回0
        }
    }
    return 1;
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值