C语言实现之牛的数量(细胞分裂问题)(利用树实现)

来源:互联网 发布:装修公司网络推广 编辑:程序博客网 时间:2024/05/16 16:55

起因:

    老师上课的时候说了一个题:

        牛长到3岁可以生小牛,长到9岁后去世,每年可以生一头小牛,最初牛圈中只有一头牛,经过X年后,牛圈里有几头牛?

    当我听完之后第一反应,9年以内是一头牛,九年之后就没牛了,有的话也只剩尸体了大笑。牛是哺乳动物,有性生殖,一头牛怎么生啊?我更喜欢称这个问题叫细胞分裂问题,比如说蛙的红细胞就是通过无丝分裂增殖的。不多扯了,还是用牛吧,我们先分析一下问题。

分析:

    牛一年生一头,从三岁开始能生小牛,他总共能活九年,最后一年它怎么这把最后一头牛生下来再死吧(YY:可能是难产死的)。这样这题就是说一头牛活九年,从三岁开始到死,总共能生7头牛。

    我们可以用什么方法解决这个问题来?

    (1)找出一个数量关系的公式,直接计算。

    (2)模拟这个生长的数量关系,(a)循环+数组,(b)循环+递归+树,(c)递归。

    小弟不才,没找出数量关系的公式。所以只能模拟,那这个牛数量的存储用什么实现?老师说用数组,但是我向大家第一个想到的应该是用树来实现吧,类似家谱。我决定用树来实现(当然题目就是这个尴尬)。

    利用树实现的缺点:当然这个确实是最符合思维的一种方法,但是缺点显而易见,效率比较低,相比数组,吃内存也比较多。

思路:

    我是这样想的,将牛看做树上的节点,便利一次就是一年,年龄0-2岁不作处理,只给他增长年龄,3-9岁没便利一次,在此节点之下创建新的结点,年龄是1的话就让全局计数的变量增长1,表示有新牛出生,年龄到达10的话就已经死了,所以就让全局计数的变量减少1,表示有一头牛死了。所以有几年,就这样遍历几次这个树,最后的计数变量就是现在牛圈中还活着的牛的数量。

    那么这个节点的结构体需要包含两部分,一个是这个节点的年龄,另一个是,指向它的子节点的7个指针。

▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
▕ago▕ node_0▕node_1▕ node_2▕ node_3▕node_4▕ node_5▕ node_6▕
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

实现:

#include <stdio.h>#include <stdlib.h>#define DIETIME 9                                   //死亡时间#define INCREASETIME 3                              //开始繁殖时间#define COUNTINCREASE DIETIME - INCREASETIME + 1    //总繁殖时间//节点typedef struct OXnode{    int age;                                        //年龄    struct OXnode * nextOX[COUNTINCREASE];          //子(小牛)节点}OX;int countOX = 0;                                    //记录牛的总数/*********************************** 函  数:OX * createNode()        ** 参  数:无                       ** 功  能:创建一个牛的节点           ** 返  回:创建好的节点的指针         ***********************************/OX * createNode(){    int loop = COUNTINCREASE;    OX * node = (OX *)malloc(sizeof(OX));      //申请内存空间    //判断内存申请是否不成功    if(node == NULL)    {        puts("not have enough memory.");        exit(0);                                //退出程序    }    node->age = 0;                              //初始化年龄    //循环初始化节点    while(loop--)    {        node->nextOX[loop] = NULL;    }    return node;                               //返回创建的节点}/*********************************** 函  数:void traversal(OX * ox)  ** 参  数:无                       ** 功  能:遍历结点                  ** 返  回:无                       ************************************/void traversal(OX * ox){    //判断年龄是否还需要增加(防止不必要的增加)    if(ox->age  <= DIETIME)    {        ox->age++;                       //年龄增加    }    //判断年龄状况    switch(ox->age)    {        case 1:                         //1岁说明是新牛            countOX++;                   //总数增加1            break;        case DIETIME:                   //9岁说明是将要死去的牛            countOX--;                   //总数减少1            break;    }    //判断牛是否到达繁衍的年龄    if(ox->age >= INCREASETIME)    {        int loop = 0;        int age = ox->age == DIETIME + 1 ? DIETIME : ox->age ;  //计算当前年龄        //循环他的子节点(即亲生的小牛节点)        for(; loop < (age - INCREASETIME + 1); loop++)        {            //判断节点是否为NULL(即此小牛刚出生)            if(ox->nextOX[loop] == NULL)            {                ox->nextOX[loop] = createNode();                //创建新生的小牛节点            }            traversal(ox->nextOX[loop]);                        //遍历此小牛节点        }    }}/********************************** 函  数:int main()              ** 参  数:无                      ** 功  能:主函数                   ** 返  回:0                       ***********************************/int main(){    int year;    puts("years:");    scanf("%d",&year);    OX * firstOX = createNode();        //创建首节点    //年数循环遍历全部节点    while(year--)    {        traversal(firstOX);             //遍历    }    printf("count : %d\n",  countOX);    return 0;}

结果:

这是前39年的结果:
    current year: 1, count: 1
    current year: 2, count: 1
    current year: 3, count: 2
    current year: 4, count: 3
    current year: 5, count: 5
    current year: 6, count: 8
    current year: 7, count: 13
    current year: 8, count: 21
    current year: 9, count: 33
    current year: 10, count: 53
    current year: 11, count: 85
    current year: 12, count: 136
    current year: 13, count: 218
    current year: 14, count: 349
    current year: 15, count: 559
    current year: 16, count: 895
    current year: 17, count: 1433
    current year: 18, count: 2295
    current year: 19, count: 3675
    current year: 20, count: 5885
    current year: 21, count: 9424
    current year: 22, count: 15091
    current year: 23, count: 24166
    current year: 24, count: 38698
    current year: 25, count: 61969
    current year: 26, count: 99234
    current year: 27, count: 158908
    current year: 28, count: 254467
    current year: 29, count: 407490
    current year: 30, count: 652533
    current year: 31, count: 1044932
    current year: 32, count: 1673299
    current year: 33, count: 2679533
    current year: 34, count: 4290863
    current year: 35, count: 6871162
    current year: 36, count: 11003117
    current year: 37, count: 17619812
    current year: 38, count: 28215439
    current year: 39, count: 45182718
    ...

总结:

主要还是思路,没有难的地方,发出来和大家分享下,希望大家多多多提意见,就写这些吧。

原创粉丝点击