球钟问题之链式队列与链式栈的应用

来源:互联网 发布: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;
}


好了   以上就是整个程序的流程了    你造吗?

0 0
原创粉丝点击