【初学C语言关于约瑟夫环问题的2种解决方法】

文章介绍了约瑟夫环问题的背景和经典算法,提供了一种使用数组解决的C语言实现方式。作者通过建立一个循环数组模拟游戏过程,遍历数组淘汰对应位置的人,直到找到最后的获胜者。代码示例展示了具体的实现细节,并提到后续会介绍其他方法。
摘要由CSDN通过智能技术生成


前言

        作为一个刚接触C语言的小白,我找了一个学过C语言的同学每天晚上给我出题,于是那天晚上第一次接触了约瑟夫环问题,当时感觉挺有意思的,第一反应是建立一个首尾相连的循环体来遍历,但因为不知道咋实现,因为那时候刚接触数组,感觉可以用数组来做,于是花了几十分钟在解决无数bug后终于能运行出结果了(具体代码和运行结果见后面),后来的后来又学了结构体和指针,终于可以实现我最终的想法了。(因为刚学C语言,文章中或代码出现的错误欢迎指正)

 

一、约瑟夫环是什么?

        约瑟夫环问题是一个很经典的问题:n个人围成一个圈子,设置一个数字炸弹为m,n个人按顺序从1开始以++的方式报数,当某个人碰到m时淘汰,并由下一个人接着从1开始循环往复,直到只剩下最后一人,求出最后一人是谁就是约瑟夫环问题的主题。用代码实现这个问题的求解,主要是要实现“循环”

二、两种方法

1.数组的方法

        这种思路一般不容易想到,但想到后思路就比较简单。我的大致思路是假如有n个人参与游戏,给每个人编号为1,2,3...n,n个人游戏最多进行n-1轮就能结束,因此笨笨的我建立了一个n*(n-1)大小的数组来实现游戏的循环,具体即为1,2,3,4...n,1,2,3,4...,n...然后通过for循环从数组第一位不断遍历,拿到炸弹的数字在整个数组中都变为0,谁拿到炸弹是根据一直遍历直到连续经过m个不为0的数字,最后经过(n-1)轮就能得出最后的答案。

代码如下(示例)

//
// Created by xsywan4520 on 2023/3/17.
//
#include <stdio.h>
#include <stdlib.h>
int main() {  //定义变量n为游戏人数,x为数字炸弹,arr为总数组
    int n, x=4;
    printf("请输入游戏人数和数字炸弹的数字:");
    scanf("%d,%d", &n, &x);
//首先创建一个n*(n-1)大小不断循环的数组,如当n=5,x=3时,arr[]={1,2,3,4,5,1,2,3,4,5}
    int *arr= calloc(n*(n-1),sizeof(int));
    if (!arr){return -1;}
    for (int i = 0; i < n; i++) { for (int j = 0; j < n - 1; j++) { arr[i + j * n] = i + 1; }}
//定义num为游戏局数,i为流转次数,d为连续流转时未碰到炸弹的次数,当有人拿到炸弹时d重置为0,temp记录当时被淘汰人的姓名
    int i = 0,d = 0, temp,num=0;
    for (; i < n * (n - 1); i++) {
        if (arr[i] != 0)d += 1;
        if (d == x) {
            num+=1;
            temp = arr[i];
//对拿到炸弹被淘汰的进行输出
            printf("淘汰的第%d个人为:%d",num,arr[i]);
            for (int k = 0; k < n * (n - 1); k++) { if (arr[k] == temp)arr[k] = 0; }
            d=0;
            printf("\n");
            if(num==n-1)break;}}
//最后对结果进行输出
    for (int h=0; h < n * (n - 1); h++) {if(arr[h]!=0){printf("最终的获胜者为:%d",arr[h]);
            free(arr);arr=NULL;return 0;}}
}

运行结果如下(实例)

总结


第二种方法有时间再写,不说了,两年半,呸,两点半了顶不住了,欢迎指正。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值