【数据结构】栈与队列的实际应用——球钟问题

球钟:

球钟为一种计时工具,其主要原理为通过小球的移动来进行实践的记录。它有三个能容纳若干球的指示器:小时指示器、五分钟指示器、分钟指示器。如果小时、五分钟、分钟指示器内存在小球分别为:5、4、1,那么其所表示的时间则为05:21。

当分钟指示器内小球达到5个时,进位到五分钟指示器,即清空分钟指示器内小球,五分钟指示器内小球加一;五分钟进位同理。在球钟问题内,球钟最多能够表示时间为11:59,再多一分钟为12:00时将自动清零。

球钟问题描述:

问题中,使用堆栈结构来表示三种指示器,使用队列结构作为小球的存储容器。初始状态下,三种指示器内小球数均为0,小球存储队列由队首到队尾存放编号为0~26的小球。(按照进位原则,分钟指示器最多存放4个小球,五分钟指示器和小时指示器最多存放11个小球,还有一个小球用于最后的进位)

问:最少经过多少分钟后,小球存储队列中的标号与初始状态相同

代码:

"linkqueue.h"和"sqstack.h"头文件分别为链式队列与顺序栈的程序头文件,具体相关内容在其他随笔内有。
#include <stdio.h>
#include "linkqueue.h"
#include "sqstack.h"
#define N 27

int check(linkqueue *lq);          //检查是否小球队列内编号顺序为0~26

int main()
{
    linkqueue *lq;
    int i;
    sqstack *s_hour,*s_five,*s_min;
    int min = 0;
    int value;

    //squeue init
    if((lq=queue_create()) == NULL){
        printf("lq is NULL\n");
        return -1;
    }
    for(i=0;i<N;i++){
        enqueue(lq,i);
    }
    //stack init
    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++;
        if(!queue_empty(lq)){    //判断队列不为空
            value = dequeue(lq);  //出队一个元素
            //s_min++
            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);    //最后一个小球进位,放回小球存储队列
                        //00:00 check
                        if(check(lq)) break;  //检查是否编号与初始状态相同(只有00:00时,队列中才存在27个小球,才可能与初始相同)
                    }
                }
            
            }
        }
    }

    //printf
    printf("min=%dmin\n",min);
    printf("hour=%dh\n",min/60);
    printf("lq is ");
    while(!queue_empty(lq)){
        printf("%d ",dequeue(lq));
    }

    puts("");


    return 0;
}

int check(linkqueue *lq){
    linklist p;
    
    if(lq == NULL){
        printf("lq is NULL");
        return -1;
    }

    p = lq->front->next;
    while(p && p->next){
        if(p->data < p->next->data)
            p = p->next;
        else 
            return 0;
    }
    return 1;
}

 

最终运行计算结果为:

 

 即:最少经过552小时,小球存储队列内的编号与初始状态相同为0~26

 

posted @ 2023-02-16 16:13  ailaopo_zhai  阅读(212)  评论(0编辑  收藏  举报