球钟问题的解决--栈和队列

球钟问题描述:球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,5分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。
    
工作原理:每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该秋种表示的时间范围是从00:00到11:59
 
请看示意图(图是从网上找的,不好勿喷啊!!):
 
思考:
    要想表示00:00到12:00需要多少个球?假设,指示器都为空,球队列需要多长时间能回到原来的状态?
答案是总共组要27个球,当每个指示器满的时候,为了保证队列不为空,所以为4+11+11+1=27。下面解决第二个问题:
 
这里我为了管理方便,采用了make工程管理器,总共有以下几个文件:
main.c  queue.c  stack.c  queue.h  stack.h  Makefile
这里的main文件不用说,肯定就是主函数,而stack.c和queue.c是分别定义栈和队列操作的函数,而两个头文件是定义这些函数的接口。
搞清楚了文件之间的关系后,请看源码:
queue.c文件:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:12px;">/************************************************************************* 
  2.     > File Name: queue.c 
  3.     > Author: Baniel Gao  
  4.     > Mail: createchance@163.com  
  5.     > Blog: blog.csdn.net/createchance  
  6.     > Created Time: 2013年12月21日 星期六 11时13分10秒 
  7.  ************************************************************************/  
  8. #include "queue.h"  
  9.   
  10. linkqueue_st *linkqueue_init(int size)  
  11. {  
  12.     linkqueue_st *queue = NULL;  
  13.   
  14.     queue = (linkqueue_st *)malloc(sizeof(linkqueue_st));  
  15.     queue->total = size;  
  16.     queue->current = 0;  
  17.     queue->head = linkqueue_node_create(0);  
  18.     queue->tail = queue->head;  
  19.   
  20.     return queue;  
  21. }  
  22.   
  23. nodequeue_st *linkqueue_node_create(int value)  
  24. {  
  25.     nodequeue_st *node = NULL;  
  26.   
  27.     node = (nodequeue_st *)malloc(sizeof(nodequeue_st));  
  28.     node->data = value;  
  29.     node->next = NULL;  
  30.   
  31.     return node;  
  32. }  
  33.   
  34. int linkqueue_enqueue(linkqueue_st *queue, int value)  
  35. {  
  36.     nodequeue_st *new = NULL;  
  37.   
  38.     if(linkqueue_isfull(queue))  
  39.         return -1;  
  40.     new = linkqueue_node_create(value);  
  41.     queue->tail->next = new;  
  42.     queue->tail = new;  
  43.     queue->current++;  
  44.   
  45.     return 0;  
  46. }  
  47.   
  48. int linkqueue_dequeue(linkqueue_st *queue, int *value)  
  49. {  
  50.     nodequeue_st *tmp;  
  51.   
  52.     if(linkqueue_isempty(queue))  
  53.         return -1;  
  54.     tmp = queue->head;  
  55.     *value = tmp->next->data;  
  56.     queue->head = tmp->next;  
  57.     free(tmp);  
  58.     queue->current--;  
  59.   
  60.     return 0;  
  61. }  
  62.   
  63. int linkqueue_isfull(linkqueue_st *queue)  
  64. {  
  65.     if(queue->current == queue->total)  
  66.         return 1;  
  67.     return 0;  
  68. }  
  69.   
  70. int linkqueue_isempty(linkqueue_st *queue)  
  71. {  
  72.     if(queue->current == 0)  
  73.         return 1;  
  74.     return 0;  
  75. }  
  76.   
  77. int linkqueue_free(linkqueue_st *queue)  
  78. {  
  79.     nodequeue_st *p = queue->head;  
  80.     nodequeue_st *tmp;  
  81.   
  82.     while(p != NULL) {  
  83.         tmp = p;  
  84.         p = p->next;  
  85.         free(tmp);  
  86.     }  
  87.     free(queue);  
  88.   
  89.     return 0;  
  90. }</span>  

这里的栈是使用的链式存储实现的,具体的思想请看本人的前几个帖子。
stack.c:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:12px;">/************************************************************************* 
  2.     > File Name: stack.c 
  3.     > Author: Baniel Gao  
  4.     > Mail: createchance@163.com  
  5.     > Blog: blog.csdn.net/createchance  
  6.     > Created Time: 2013年12月21日 星期六 11时13分18秒 
  7.  ************************************************************************/  
  8. #include "stack.h"  
  9.   
  10. seqstack_st *seqstack_init(int size)  
  11. {  
  12.     seqstack_st *stack = NULL;  
  13.   
  14.     stack = (seqstack_st *)malloc(sizeof(seqstack_st));  
  15.     stack->total = size;  
  16.     stack->top = 0;  
  17.     stack->data = (int *)malloc(sizeof(int) * size);  
  18.   
  19.     return stack;  
  20. }  
  21.   
  22. int seqstack_push(seqstack_st *stack, int value)  
  23. {  
  24.     if(seqstack_isfull(stack))  
  25.         return -1;  
  26.     stack->data[stack->top++] = value;  
  27.   
  28.     return 0;  
  29. }  
  30.   
  31. int seqstack_pop(seqstack_st *stack, int *value)  
  32. {  
  33.     if(seqstack_isempty(stack))  
  34.         return -1;  
  35.     *value = stack->data[--stack->top];  
  36.   
  37.     return 0;  
  38. }  
  39.   
  40. int seqstack_isfull(seqstack_st *stack)  
  41. {  
  42.     if(stack->top == stack->total)  
  43.         return 1;  
  44.     return 0;  
  45. }  
  46.   
  47. int seqstack_isempty(seqstack_st *stack)  
  48. {  
  49.     if(stack->top == 0)  
  50.         return 1;  
  51.     return 0;  
  52. }  
  53.   
  54. int seqstack_free(seqstack_st *stack)  
  55. {  
  56.     free(stack->data);  
  57.     free(stack);  
  58.   
  59.     return 0;  
  60. }</span>  

这里的栈实现是使用的连续存储实现的,具体的思想比较简单,就不多说了。
两个头文件:
queue.h:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:12px;">/************************************************************************* 
  2.     > File Name: queue.h 
  3.     > Author: Baniel Gao  
  4.     > Mail: createchance@163.com  
  5.     > Blog: blog.csdn.net/createchance  
  6.     > Created Time: 2013年12月21日 星期六 12时01分54秒 
  7.  ************************************************************************/  
  8. #ifndef _QUEUE_H_  
  9. #define _QUEUE_H_  
  10.   
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13.   
  14. typedef struct _nodequeue_ {  
  15.     int data;  
  16.     struct _nodequeue_ *next;  
  17. } nodequeue_st;  
  18.   
  19. typedef struct _linkqueue_ {  
  20.     int total;  
  21.     int current;  
  22.     nodequeue_st *head;  
  23.     nodequeue_st *tail;  
  24. } linkqueue_st;  
  25.   
  26. linkqueue_st *linkqueue_init(int size);  
  27. nodequeue_st *linkqueue_node_create(int value);  
  28. int linkqueue_enqueue(linkqueue_st *queue, int value);  
  29. int linkqueue_isfull(linkqueue_st *queue);  
  30. int linkqueue_dequeue(linkqueue_st *queue, int *value);  
  31. int linkqueue_isempty(linkqueue_st *queue);  
  32. int linkqueue_free(linkqueue_st *queue);  
  33.   
  34. #endif</span>  

stack.h:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:12px;">/************************************************************************* 
  2.     > File Name: stack.h 
  3.     > Author: Baniel Gao  
  4.     > Mail: createchance@163.com  
  5.     > Blog: blog.csdn.net/createchance  
  6.     > Created Time: 2013年12月21日 星期六 11时58分18秒 
  7. ************************************************************************/  
  8. #ifndef _STACK_H_  
  9. #define _STACK_H_  
  10.   
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13.   
  14. typedef struct _seqstack_ {  
  15.     int total;  
  16.     int top;  
  17.     int *data;  
  18. } seqstack_st;  
  19.   
  20. seqstack_st *seqstack_init(int size);  
  21. int seqstack_push(seqstack_st *stack, int value);  
  22. int seqstack_isfull(seqstack_st *stack);  
  23. int seqstack_pop(seqstack_st *stack, int *value);  
  24. int seqstack_isempty(seqstack_st *stack);  
  25. int seqstack_free(seqstack_st *stack);  
  26.   
  27. #endif</span>  

下面请看最关键的主函数的实现:
main.c:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:12px;">/************************************************************************* 
  2.     > File Name: main.c 
  3.     > Author: Baniel Gao  
  4.     > Mail: createchance@163.com  
  5.     > Blog: blog.csdn.net/createchance  
  6.     > Created Time: 2013年12月21日 星期六 11时13分24秒 
  7.  ************************************************************************/  
  8. #include "queue.h"  
  9. #include "stack.h"  
  10.   
  11. int queue_check(linkqueue_st *queue);  
  12. void debug(linkqueue_st *queue);  
  13.   
  14. int main(void)  
  15. {  
  16.     int timer = 0;  
  17.     int value = 1;  
  18.     int tmp;  
  19.     int queue_size = 27;  
  20.     int stack_m1_size = 4;  
  21.     int stack_m5_size = 11;  
  22.     int stack_h1_size = 11;  
  23.     linkqueue_st *queue;  
  24.     seqstack_st *stack_m1;  
  25.     seqstack_st *stack_m5;  
  26.     seqstack_st *stack_h1;  
  27.       
  28.     queue = linkqueue_init(queue_size);  
  29.     stack_m1 = seqstack_init(stack_m1_size);  
  30.     stack_m5 = seqstack_init(stack_m5_size);  
  31.     stack_h1 = seqstack_init(stack_h1_size);  
  32.     while(-1 != linkqueue_enqueue(queue, value))  
  33.         value++;  
  34.     while(1) {  
  35.         linkqueue_dequeue(queue, &value);  
  36.         if(-1 != seqstack_push(stack_m1, value))  
  37.             continue;  
  38.       
  39.         while(-1 != seqstack_pop(stack_m1, &tmp))  
  40.             linkqueue_enqueue(queue, tmp);  
  41.       
  42.         if(-1 != seqstack_push(stack_m5, value))  
  43.             continue;  
  44.   
  45.         while(-1 != seqstack_pop(stack_m5, &tmp))  
  46.             linkqueue_enqueue(queue, tmp);  
  47.   
  48.         if(-1 != seqstack_push(stack_h1, value))  
  49.             continue;  
  50.   
  51.         while(-1 != seqstack_pop(stack_h1, &tmp))  
  52.             linkqueue_enqueue(queue, tmp);  
  53.   
  54.         linkqueue_enqueue(queue, value);  
  55.         timer++;  
  56.         debug(queue);  
  57.         if(queue_check(queue))  
  58.             break;  
  59.     }  
  60.     printf("The time is %d hours!\n", timer*12);  
  61.   
  62.   
  63.     linkqueue_free(queue);  
  64.     seqstack_free(stack_m1);  
  65.     seqstack_free(stack_m5);  
  66.     seqstack_free(stack_h1);  
  67.   
  68.     return 0;  
  69. }  
  70. void debug(linkqueue_st *queue)  
  71. {  
  72.     nodequeue_st *p = queue->head->next;  
  73.   
  74.     while(p != NULL) {  
  75.         printf("%d  ", p->data);  
  76.         p = p->next;  
  77.     }  
  78.     putchar('\n');  
  79. }  
  80.   
  81. int queue_check(linkqueue_st *queue)  
  82. {  
  83.     nodequeue_st *p = queue->head->next;  
  84.   
  85.     while(p != NULL && p->next != NULL) {  
  86.         if(p->data > p->next->data)  
  87.             return 0;  
  88.         p = p->next;  
  89.     }  
  90.   
  91.     return 1;  
  92. }</span>  

其中的debug函数是为了方便调试而设置的,并且可以用它来打印每隔12个小时的队列情况
下面是Makefile:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:12px;">CC:= gcc  
  2. CFLAGS:= -Wall -O2 -c  
  3. OBJ:= ballclock  
  4.   
  5. .PHONY: clean memcheck  
  6.   
  7. $(OBJ): main.o stack.o queue.o  
  8.     $(CC) -o $@ $^  
  9. main.o: main.c stack.h queue.h  
  10.     $(CC) -o $@ $< $(CFLAGS)  
  11. queue.o: queue.c queue.h  
  12.     $(CC) -o $@ $< $(CFLAGS)  
  13. stack.o: stack.c stack.h  
  14.     $(CC) -o $@ $< $(CFLAGS)  
  15.   
  16. clean:  
  17.     rm -rf *.o $(OBJ)  
  18.   
  19. memcheck:  
  20.     valgrind --tool=memcheck ./$(OBJ)</span>  

这个问题看似很难,其实用计算机程序来实现的话是不难的,只要找到基本规律,然后用循环让计算机不停地去做就可以了。
运行结果是552个小时,也就是23天!!

原文出处:http://blog.csdn.net/createchance/article/details/17466053
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值