数据结构之链式队列与链式栈的应用-球钟问题

在数据结构的栈和队列的学习过程中,除了需要了解栈、队列的基本特点外,需要掌握包括创建、出栈入栈、出队入队等基本操作。并熟悉一些常见的应用问题,比如球钟问题就是一个典型利用栈和队列实现的实际问题。本文描述球钟问题的具体实现过程。

球钟问题描述问题描述:球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。

工作原理:每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该球钟表示时间的范围是从0:00到11:59。

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

球钟问题程序流程图如下,S1、S5、S60分别为1分钟、5分钟、60分钟栈,队列出队成员赋值给x。

#ifndef __DATA__H
#define __DATA__H

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>

typedef int DataType;
//定义结点类型
struct node 
{
    DataType data;

    struct node *next;
};

#endif

#ifndef __LINKQUEUE__H
#define __LINKQUEUE__H

#include "data.h"

//#include <stdio.h>/*{{{*/
//#include <stdlib.h>
//#include <string.h>
//
//typedef int DataType;
结点类型
//struct node
//{
//    DataType data;
//    struct node *next;
//};/*}}}*/

队列头/*{{{*/
//typedef struct
//{
//    //front指向链表头
//    struct node *front;
//    //rear指向链表尾
//    struct node *rear;
//}LinkQueue;
//
//extern LinkQueue *creat_linkqueue();
//extern int is_empty_linkqueue(LinkQueue *q);
//extern int enter_linkqueue(LinkQueue *q,DataType data);
//extern DataType delete_linkqueue(LinkQueue *q);
///*}}}*/

//队列头
typedef struct
{
    //front指向链表头
    struct node *front;
    //rear指向链表尾
    struct node *rear;
}LinkQueue;

extern LinkQueue *creat_linkqueue();
extern int is_empty_linkqueue(LinkQueue *q);
extern int enter_linkqueue(LinkQueue *q,DataType data);
extern DataType delete_linkqueue(LinkQueue *q);

#endif

#ifndef __LKSTACK__H
#define __LKSTACK__H

#include "data.h"

//#include <stdio.h>/*{{{*/
//#include <stdlib.h> 
//#include <string.h>
//
//typedef int DataType;
定义结点类型
//struct node 
//{
//    DataType data;
//
//    struct node *next;
//};/*}}}*/

//栈头类型
typedef struct
{
    //指向栈顶结点
    struct node *top;
    //记录栈中元素
    int n;
}LinkStack;

extern LinkStack *create_empty_stack();
extern int is_empty_stack(LinkStack *s);
extern int push_linkstack(LinkStack *s,DataType data);
extern DataType pop_linkstack(LinkStack *s);
extern DataType get_top_data(LinkStack *s);
#endif 

#include "linkqueue.h"



//新建一个队列头
LinkQueue *creat_linkqueue()
{
    //先分配一个头结点,head保存其地址
    //在为队列头在堆区分配空间,q保存其首地址
    struct node *head = NULL;
    LinkQueue *q = NULL;

    //创建空链表,链表队列头结点
    head = (struct node *)malloc(sizeof(struct node));
    memset(head,0,sizeof(struct node));//清空后指针域为NULL。表示空链表

    //队列头,指向链表头跟链表尾
    q = (LinkQueue *)malloc(sizeof(LinkQueue));
 
    q->front = head;
    q->rear = head;

    return q; 
}

///链表判空
int is_empty_linkqueue(LinkQueue *q)
{
    return q->front == q->rear;
}

//尾插法插入数据
int enter_linkqueue(LinkQueue *q,DataType data)
{
    struct node *temp = NULL;

    temp = (struct node *)malloc(sizeof(struct node));
    temp->data = data;
    
    temp->next = q->rear->next;
    q->rear->next = temp;

    //更新rear
    q->rear = temp;

    return 0;

}

//删头法对头数据出队
DataType delete_linkqueue(LinkQueue *q)
{
    struct node *temp = NULL;

    //保存原头结点首地址
    temp = q->front;

    //更新front
    q->front = q->front->next;

    free(temp);

    temp = NULL;


    return  q->front->data;
}
#include "lkstack.h"


//创建空栈
LinkStack *create_empty_stack()
{
    LinkStack *s =NULL;


    s = (LinkStack*)malloc(sizeof(LinkStack));


    s->top = NULL;
    s->n = 0;


    return s;
}


//栈判空
int is_empty_stack(LinkStack *s)
{
    //return s->n;
    return s->top == NULL;
}


int push_linkstack(LinkStack *s,DataType data)
{
    struct node *temp = NULL;


    temp = (struct node*)malloc(sizeof(struct node));
    temp->data = data;


    temp->next = s->top;//在新结点后链接链式栈
    s->top = temp;//更新栈顶指针
    s->n++;//跟新栈元素个数


    return 0;
}


//出栈
DataType pop_linkstack(LinkStack *s)
{
    struct node *temp  = NULL;
    DataType data;


    temp = s->top ;
    data = temp->data;


    s->top =  s->top->next;
    s->n--;


    free(temp);


    return data;
}


DataType get_top_data(LinkStack *s)
{
    return s->top->data;
}
#include "data.h"
#include "lkstack.h"
#include "linkqueue.h"


//判断队列内的钟球是不是按照0-26的顺序排列的
//若是则返回0,若不是则返回-1
int is_order_linkqueue(LinkQueue *lq)
{
    int i = 0;
    //LinkQueue *temp = lq;


    struct node *temp = lq->front->next;//这里为什么要指向front->next呢?????
    //为什么呢??????
    //为什么呢???????
    
    //struct node *temp = lq->front;


    //while(delete_linkqueue(lq) != i++)
    for(i = 0;i < 27;i++)
    {
        if(temp->data != i)
            return 0;
        temp = temp->next;
    }


    return 1;


}




int main()
{


    int time = 0;
    int i = 0;
    int flag = 0;
    int ball_data = 0;
    int temp_ball = 0;
    int minute = 0;


    LinkQueue *lq= NULL;//定义一个链式队列头
    LinkStack *ls_1s = NULL;//定义一个一分钟的链式栈头
    LinkStack *ls_5s = NULL;//定义一个五分钟的链式栈头
    LinkStack *ls_1h = NULL;//定义一个一小时的链式栈头 


    lq = creat_linkqueue();//创建一个链式队列,用lq指向队列头队列尾说明为空队列
    //lq->front = lq->rear = NULL;//因为在创建新队列时已经将队头队尾初始化


    ls_1s = create_empty_stack();//创建一个一分钟链式空栈
    ls_5s = create_empty_stack();//创建一个五分钟链式空栈
    ls_1h = create_empty_stack();//创建一个一小时链式空栈


    for(i = 0;i < 27;i++)
    {
        enter_linkqueue(lq,i);
    }


    while(!is_empty_linkqueue(lq))/*{{{*/
    //for(i = 26;i >= 0;i--)
    //{
    //    printf("%-3d",delete_linkqueue(lq));
    //}
    //putchar('\n');/*}}}*/


    //ball_data = delete_linkqueue(lq);   
    //while(!is_order_linkqueue(lq))
    while(!flag)
    {
       minute++;
       ball_data = delete_linkqueue(lq);   
       if(ls_1s->n < 4)
       {
           push_linkstack(ls_1s,ball_data);
           //ball_data = delete_linkqueue(lq);
       }
       else
       {
           while(!is_empty_stack(ls_1s))
           {
               //temp_ball = pop_linkstack(ls_1s);
               //enter_linkqueue(lq,temp_ball);
               enter_linkqueue(lq,pop_linkstack(ls_1s));
           }
           if(ls_5s->n < 11)
           {
               push_linkstack(ls_5s,ball_data);
               //ball_data = delete_linkqueue(lq);
           }
           else
           {
               while(!is_empty_stack(ls_5s))
               {
                   temp_ball = pop_linkstack(ls_5s);
                   enter_linkqueue(lq,temp_ball);
               }
               if(ls_1h->n < 11)
               {
                   push_linkstack(ls_1h,ball_data);
                   //ball_data = delete_linkqueue(lq);
               }
               else
               {
                   while(!is_empty_stack(ls_1h))
                   {
                       temp_ball = pop_linkstack(ls_1h);
                       enter_linkqueue(lq,temp_ball);
                   }
                   enter_linkqueue(lq,ball_data);
                   if(is_order_linkqueue(lq))
                   {
                       flag = 1;
                   }
               }
           }
       }
    time = minute / 60;
    printf("%d day:%d hour:%d minute\n",time/24,time%24,minute%60);
    }
    //time = minute / 60;
    //printf("%d day:%d hour:%d minute\n",time/24,minute%24,minute%60%24);
    //printf("%d day:%d hour:%d minutse\n",minute/60/20,minute%24/60,minute%20%60);
    //printf("");


    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值