鱼C论坛

 找回密码
 立即注册

约瑟夫自杀问题 代码附详细注解

已有 385 次阅读2019-8-16 11:52

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏 —— 摘自百度百科《约瑟夫问题》

typedef struct node {
    int data ;
    struct node *next ;
} node ;

node *create (int ppl);

int main ()
{
    int ppl = 41 ; // 可自定义
    int dead = 3 ; // 报数报到第几个人就得自杀,可自定义
    int i = 1 ; // 计数器
    node *target = create(ppl); // 创建循环链表
    node *tmp = NULL ; // 临时指针,用于删除链表用
    while (target != target->next) // 如果最后只剩一个人,他的下家还是自己,就跳脱循环
    {
        for (i = 1 ; i < dead-1 ; i++) // 循环一次
        {
            target = target->next ; // 第二位
        }
        printf("%d --> ",target->next->data); // 再步进一位,第三位,处死
        tmp = target->next ; // 访问第三位,tmp即将被释放
        target->next = tmp->next ; // 第二位的下家赋予给第四位
        free(tmp) ; // 释放
        target = target->next ; // 复位,把第四位作为起始报数人
    }
    printf("%d\n",target->data); // 打印最后一位,因为它没有进入循环
    return 0 ;
}

node *create (int ppl)
{
    node *head = NULL ;
    head = (node*)malloc(sizeof(node)); // 动态分配空间
    node *tmp = head ; // 临时指针
    node *add = NULL ; // 新结点指针
    int i = 1 ;
    while (i <= ppl) // i作为每个成员的编号
    {
        add = (node *)malloc(sizeof(node)); // 动态分配空间
        add->data = i++ ; // i随着步进而作为成员的编号被录入
        tmp->next = add ; // 尾插法
        tmp = add ;
    }
    tmp->next = head->next ; // 最后一个结点指向头指针的下家,即编号为1的成员
    free(head); // 释放头结点
    return tmp->next ; // 返回一个以头结点的下家(即第一个被编号的成员)的链表
}

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 14:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部