球钟问题之链式队列与链式栈的应用
来源:互联网 发布:w10网络连接图标不见了 编辑:程序博客网 时间:2024/06/04 20:29
球钟问题描述:
球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,5分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。
每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。当放入第五个球时,在分钟指示器内的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该球种表示的时间范围是从00:00到11:59
要想表示00:00到12:00最少需要多少个球?
假设,指示器都为空,球队列需要多长时间能回到原来的状态?即从初始球队列中球的顺序,经过球的循环后球队列中的球再次与初始顺序相同
解题思路:
当然解此问题,首先我们要创建三个栈,分别存放各个类型的球,再构建一个队列存放原先球的个数 ,从队列中,按照题目要求分别累计放球,其实问题的思路很好理解,有的时候之所以没有思路 , 只是把问题复杂化了而已 , 要用淡定的眼光去发现问题,这样才能看出问题的本质。
以27个球为例讲解整体思路
以下为头文件的创建
#ifndef _HEAD_H_
#define _HEAD_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//新建一个链式队列
#define N 27
typedef int data_t;
//链表节点类型
typedef struct node
{
data_t data;
struct node *next;
}linknode_t;
//链式队列类型
typedef struct
{
linknode_t * rear;
linknode_t * front;
}linkqueue_t;
extern linkqueue_t * create_linkqueue(); //创建一个新的队列
extern int is_empty_linkqueue(linkqueue_t *q); //判断一个队列是否为空
extern int enter_linkqueue(linkqueue_t *q,data_t data); //入队
extern data_t delete_linkqueue(linkqueue_t *q); // 出队
//新建一个链式栈
typedef struct
{
linknode_t *top;
int n;//时刻记录当前中成员的个数
}linkstack_t;
extern linkstack_t *create_linkstack();//创建一个新的空链栈
extern int is_empty_linkstack(linkstack_t *s);//判空链式栈
extern int push_linkstack(linkstack_t *s,data_t data); //压栈
extern data_t pop_linkstack(linkstack_t *s); //出栈
extern data_t get_top_linkstack(linkstack_t * s); //得到栈顶元素
#endif
以下是链式队列的创建
#include "head.h"
//创建新的队列
linkqueue_t *create_linkqueue()
{
linknode_t *head = NULL;
head = (linknode_t *)malloc(sizeof(linknode_t));
head->next = NULL;
linkqueue_t * q = NULL;
q = (linkqueue_t *)malloc(sizeof(linkqueue_t));
q->rear = q->front = head;
return q;
}
//判断队列是否为空
int is_empty_linkqueue(linkqueue_t * q)
{
return q->rear == q->front;
}
//入队 只与rear有关
int enter_linkqueue(linkqueue_t *q,data_t data)
{
linknode_t *temp = NULL;
temp = (linknode_t *)malloc(sizeof(linknode_t));
temp->data = data;//保存入队的数值
temp->next = q->rear->next;
q->rear->next = temp; //把新的节点地址付给原来的指针域
q->rear = temp; //更新队尾指针的指向
return 0;
}
//出队
data_t delete_linkqueue(linkqueue_t * q)
{
linknode_t *temp = NULL;
temp = q->front; //保存元节点的首地址
q->front = temp->next;
free(temp);
temp = NULL;
return q->front->data; //
}
#if 0 // 测试该链式队列是否有误 使用时注释下就行
int main()
{
int i = 0;
linkqueue_t * q;
q = create_linkqueue();
for(i = 0; i< 10;i++)
{
enter_linkqueue(q,i);
}
while(!is_empty_linkqueue(q))
{
printf("%-3d",delete_linkqueue(q));
}
printf("\n");
return 0;
}
#endif
//链式栈的函数编写
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int data_t;
typedef struct node
{
data_t data;
struct node * next;
}linknode_t;
typedef struct
{
linknode_t *top;
int n;
}linkstack_t;
//创建一个空的栈
linkstack_t *create_linkstack()
{
linkstack_t *s = NULL;
s = (linkstack_t *)malloc(sizeof(linkstack_t));
memset(s,0,sizeof(linkstack_t));
return s;
}
//判断栈是否为空
int is_empty_linkstack(linkstack_t *s)
{
return s->top == NULL;
}
//入栈
int push_linkstack(linkstack_t *s,data_t data)
{
linknode_t *temp = NULL;
temp = (linknode_t *)malloc(sizeof(linknode_t));
temp->data = data;
temp->next = s->top;
s->top = temp;
s->n ++; //每次入栈一个元素 更新一次记录
return 0;
}
//出栈
data_t pop_linkstack(linkstack_t *s)
{
data_t data = 0;
linknode_t *temp = NULL;
// temp = (linknode_t *)malloc(sizeof(linknode_t));
temp = s->top;
data = temp->data;
s->top = temp->next;
free(temp);
temp = NULL;
s->n --;
return data;
}
//取出栈顶元素
data_t get_top_data(linkstack_t *s)
{
return s->top->data;
}
#if 0
int main()
{
int i = 0;
linkstack_t *s = NULL;
s = create_linkstack();
// is_empty_link_stack(s);
while(i != 10)
{
push_linkstack(s,i++);
}
printf("The stack of top is %d\n",get_top_data(s));
while(!is_empty_linkstack(s))
printf("%-3d",pop_linkstack(s));
putchar('\n');
return 0;
}
#endif
//主函数的实现 其实上面的所有你都可以把他们单独的放在一个地方 如果将来有某个程序 需要用到链式队列或链式栈的时候 你可以直接把他们拷贝到开发的目录下面 直接调用就行 既简化了开发的难度 有节省了时间
# include "head.h"
//只是一个测试函数 可以不写
int print_linklist(linknode_t *head)
{
linknode_t *p = head->next;
while(p)
{
printf("%-4d",p->data);
p = p->next;
}
putchar('\n');
return 0;
}
//判断是否是和之前的一样的函数
int is_orignal_queue(linkqueue_t *q)
{
linknode_t *p = q->front->next;
int i = 1;
for(i = 1;i <= N;i++)
{
if(p->data != i)
return 0;
p = p->next;
}
return 1;//若都一样了返回1
}
int ball_clock()
{
linkstack_t *min_stack = NULL,//创建的三个栈
*min5_stack = NULL,
*hour_stack = NULL;
linkqueue_t *ball_queue = NULL;
int half_day = 0;
int ball = 0;
min_stack = create_empty_linkstack();
min5_stack = create_empty_linkstack();
hour_stack = create_empty_linkstack();
ball_queue = create_empty_linkqueue();
for(ball = 1;ball <= N;ball++)
{
enter_linkqueue(ball_queue,ball);
}
//print_linklist(ball_queue->front);
while(1)
{
ball = delete_linkqueue(ball_queue);
if(min_stack->n < 4)
{
push_linkstack(min_stack,ball);
continue;
}
while(!is_emtpy_linkstack(min_stack))
{
enter_linkqueue(ball_queue,pop_linkstack(min_stack));
}
if(min5_stack->n < 11)
{
push_linkstack(min5_stack,ball);
continue;
}
while(!is_emtpy_linkstack(min5_stack))
{
enter_linkqueue(ball_queue,pop_linkstack(min5_stack));
}
if(hour_stack->n < 11)
{
push_linkstack(hour_stack,ball);
continue;
}
while(!is_emtpy_linkstack(hour_stack))
{
enter_linkqueue(ball_queue,pop_linkstack(hour_stack));
}
enter_linkqueue(ball_queue,ball);
half_day++;
//print_linklist(ball_queue->front);
if(is_orignal_queue(ball_queue))
break;
}
return half_day / 2;
}
int main()
{
int day_count = 0;
day_count = ball_clock();
printf("Restoring orignal queue need %d days\n",day_count);
return 0;
}
好了 以上就是整个程序的流程了 你造吗?
- 数据结构之链式队列与链式栈的应用-球钟问题
- 球钟问题之链式队列与链式栈的应用
- 链式队列的实现与项目中的应用
- 循环队列与链式队列的实现
- 算法与数据结构之队列的链式存储
- 数据结构之链式队列
- 数据结构之链式队列
- 数据结构之链式队列
- 数据结构之链式队列
- 队列的链式存储结构与操作
- 队列的链式表示与实现
- 队列的链式存储结构与操作
- 队列的链式表示与实现
- 队列的链式存储与顺序存储
- 链式队列的定义与操作
- 队列的连续与链式实现
- 链式队列的基本操作与实现
- 算法入门之队列的链式表示
- C# native
- android压力测试软件monkey
- spring的InitializingBean的 afterPropertiesSet 方法 和 init-method配置的 区别联系
- HDU 2662 Coin
- Codeforces Round #259 (Div. 2) 题解
- 球钟问题之链式队列与链式栈的应用
- IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解
- hdu 1016 Prime Ring Problem(深搜就可以)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- 两个ListView 实现 淘点点 点菜界面效果
- ASP.NET大闲话:ashx文件有啥用
- SSH框架 の 学习笔记(一)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Codeforces Round #259 (Div. 2) B. Little Pony and Sort by Shift(模拟)