数据结构 球钟问题

学到数据结构时,遇到一个题目:球钟
问题描述:球钟是利用球的移动来记录时间的装置(吐槽:这么麻烦,球会准时放进去?)。它有三个可以容纳若干个球的容器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,5分钟指示器中有3个球,小时指示器中有4个球,则时间为4:17。每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。在放进去第五个球的时候,分钟指示器内的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。因此,该球种表示的时间范围是从00:00到11:59

1、要想表示00:00到12:00最少需要多少个球?
2、假设,指示器都为空,球队列需要多长时间能回到原来的状态?
即从初始球队列中球的顺序,经过球的循环后球队列中的球再次与初始顺序相同。
对于第一个问题
在这里插入图片描述
想象一下,在11:59的时候,分钟指示器里面有4个球,五分钟指示器有11个球,小时指示器有11个球,则这时三个指示器都为临界状态,共用去26个球,而球钟要求能表示12:00,即可理解为00:00,就是要求能从11:59回到00:00,则还需一个球去触发这个临界状态,类似于多米洛骨牌,这个球依次进入三个指示器,并触发其临界状态,三个指示器里的球依次回到队列,然后最后一个球也回到队列,则最少需要27个球。
第二个问题
这时,要理解,回到原来的状态,并不仅仅是27个球都回到队列就完事了!!而且27个球的顺序要和原来一摸一样。
对于这个问题,没得说,敲出来算一下。
那么,既然是数据结构的问题,这题肯定是用数据结构的知识去解答,题中的队列很好理解,队首出队尾进嘛,已经明说了用队列去表示,而三个指示器要求按他们的球放入的相反顺序取出,换句话说,就是后进的先出,先进的后出,就是用三个栈去表示三个指示器。
队列的话这里可以用链式队列、顺序循环队列,不能用单纯的顺序队列,不然就假溢出了。这里我用的顺序循环队列,代码上稍微省事一点。然后用了三个链式栈。代码如下

头文件:qiuzhong.h
#ifndef _QIUZHONG_
#define _QIUZHONG_

#define minite           4
#define five_minite      11
#define hour             11 
#define num              28

typedef struct st_node
{
	int data;
	struct st_node *next;
}node,*node_p;

typedef struct st_stack
{
	int n;
	node_p top;
}stack,*stackp;

typedef struct queue_st
{
	int a[num];
	int front;
	int rear;
}queue;


extern queue *createqueue();
extern int queueempty(queue *s);
extern int queuefull(queue *s);
extern int queue_in(queue *s,int data);
extern int queue_out(queue *s);
extern stackp creatstack();
extern int empty_stack(stackp s);
extern int stack_in(stackp s,int data);
extern int stack_out(stackp s);
extern int show_queue(queue *s);
extern int clear_stack(stackp s,queue *q);
extern int queue_traverl(queue *s,int flag);

#endif

操作函数qiuzhong.c
#include <stdio.h>
#include "qiuzhong.h"
#include "stdlib.h"

queue *createqueue()
{
	queue *s=NULL;
	s=(queue *)malloc(sizeof(queue));

	if(s==NULL)
	{
		printf("malloc error!\n");
		return NULL;
	}

	s->front=0;
	s->rear=0;

	return s;
}

int queueempty(queue *s)
{
	return s->front==s->rear?1:0;
}

int queuefull(queue *s)
{
	return (s->rear+1)%num==s->front?1:0;
}

int queue_in(queue *s,int data)
{
	if(queuefull(s))
	{
		printf("the queue is full!\n");
		return -1;
	}

	s->a[s->rear]=data;
	s->rear=(s->rear+1)%num;
}

int queue_out(queue *s)
{
	int ret=0;
	if(queueempty(s))
	{
		printf("the queue is empty!\n");
		return -1;
	}

	ret=s->a[s->front];
	s->front=(s->front+1)%num;

	return ret;
}

int show_queue(queue *s)
{
	int i=s->front;
	for(;i!=s->rear;i=(i+1)%num)
	{
		printf("%d ",s->a[i]);
	}

	printf("\n");
}

int queue_traverl(queue *s,int flag)
{
	int i=0;
	int j=s->front;

	for(i=1;i<28;i++)
	{
		if(s->a[j]==i)
			j=(j+1)%num;
		else
			break;
	}
	if(i==28)
	{
		printf("顺序回原:");
		show_queue(s);
		printf("经过%d分钟队列完全回原\n",flag);
	}
}

/*---------------------------------------------*/

stackp creatstack()
{
	stackp s=NULL;
	
	s=(stackp)malloc(sizeof(stack));
	if(s==NULL)
	{
		printf("malloc error1\n");
		return NULL;
	}

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

	return s;
}


int empty_stack(stackp s)
{
	return s->top==NULL?1:0;
}

int stack_in(stackp s,int data)
{
	node_p p=NULL;

	p=(node_p)malloc(sizeof(node));
	if(p==NULL)
	{
		printf("malloc error!\n");
		return -1;
	}

	p->next=s->top;
	s->top=p;
	p->data=data;
	s->n++;
}

int stack_out(stackp s)
{
	if(empty_stack(s))
	{
		printf("the stack is empty!\n");
		return -1;
	}

	node_p p=NULL;
	int ret=0;

	p=s->top;
	ret=p->data;

	s->top=s->top->next;
	free(p);
	s->n--;

	return ret;
}


int clear_stack(stackp s,queue *q)
{
	int a;
	int i=s->n;
	for(;i>0;i--)
	{
		a=stack_out(s);
		queue_in(q,a);
	}
}

主函数main.c
#include <stdio.h>
#include "qiuzhong.h"

int main()
{
	int qd=0;
	int md=0,fd=0,hd=0;
	int xunhuan=0;
	int flag=0;


	queue *s=createqueue();
	for(qd=0;qd<27;qd++)
	{
		queue_in(s,qd+1);
	}
	
	stackp m=creatstack();
	stackp f=creatstack();
	stackp h=creatstack();
	
	printf("Please input your data:");
	scanf("%d",&xunhuan);
/*输入数据,开始循环*/
	while(xunhuan--)   //进行判断,时分秒循环
	{
		qd=queue_out(s);
		if(m->n<4)
			stack_in(m,qd);
		else
		{
			if(f->n<11)
			{
				clear_stack(m,s);
				stack_in(f,qd);
			}
			else
			{
				if(h->n<11)
				{
					clear_stack(m,s);
					clear_stack(f,s);
					stack_in(h,qd);
				}
				else
				{
					clear_stack(m,s);
					clear_stack(f,s);
					clear_stack(h,s);
					queue_in(s,qd);
				}
			}
		}
	flag++;
	queue_traverl(s,flag);
	}
/*-----------------时间换算显示-----------*/
	printf("the time is:%d:%d\n",h->n,f->n*5+m->n);

}

运行效果如图:
在这里插入图片描述
这里输入40000,让程序循环40000分钟,则经过33120分钟的时候队列完全回原,且第40000分钟的时间是6:40

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值