约瑟夫(Josephus)问题

本文探讨了一个经典的计算机科学问题——约瑟夫环。通过创建一个链表来模拟古代法官判决犯人的荒唐逻辑,文章详细解释了如何使用C语言编程解决这个问题,包括犯人处决顺序的确定和最后幸存者的预测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

古代某法官要判决n个犯人死刑,他有一条荒唐的逻辑,将犯人首尾相接排成圆圈,然后从第s个人开始数起,每数到第m个犯人,就拉出来处决;然后又数m个,数到的犯人又拉出来处决,以此类推。剩下的最后一人可以赦免。
编写程序,给出处决顺序,并给出哪一个人可以活下来。
注:大体的思路以及需要注意的点都在注释中了,直接上代码了。

//定义结点
typedef struct _josephus
{
    int num;
    struct _josephus *next;
}josephus;

int n;  //全局变量,记录共有几名犯人(结点)

//犯人数目(创建结点)
josephus *Creat(josephus *pHead)
{
    josephus *pEnd,*pNew;
    int i;
    printf("犯人数:");
    scanf("%d",&n);
    for(i = 1; i <= n; i++)
    {
        pNew = (josephus *)malloc(sizeof(josephus));
        pNew->num = i;
        pNew->next = NULL;
        if(pHead == NULL)
            pHead = pNew;
        else
            pEnd->next = pNew;
        pEnd = pNew;
    }
    pEnd->next = pHead;     //令尾指针指向头结点
    return pHead;
}

//处决函数
josephus *fun(josephus *pHead, int s, int m)
{
    josephus *temp = pHead;
    josephus *p = NULL;     //指向要处决的犯人(结点)
    int i;

    //遍历寻找到起始位置
    for(i = 1; i < s; i++)
        temp = temp->next;

    printf("kill: ");
    //循环判断处决犯人(删除结点)
    while(n > 1)
    {
        p = temp;
        for(i = 1; i < m; i++)
        {
            temp = p;
            p = p->next;
        }
        printf("%d ",p->num);
        temp->next = p->next;   //将要处决的犯人(结点)前后连接起来
        free(p);
        temp = temp->next;      //处决完一次后,还要继续处决到只剩一个犯人,因此temp指向被删除结点的下一个结点
        n--;
    }
    printf("\n");
    return temp;
}

int main()
{
    int s,m;
    
    josephus *pHead = NULL;
    pHead = Creat(pHead);
    
    printf("s,m: ");
    scanf("%d %d",&s,&m);
    pHead = fun(pHead,s,m);
    
    printf("存活: %d\n",pHead->num);
    free(pHead);
    pHead = NULL;   //防止产生野指针
    return 0;
}

!@#$%^&*~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值