约瑟夫环问题(数组法)c语言实现

约瑟夫环问题(数组法)C语言实现

问题描述

有 $n$ 个人围成一圈,第 $m$ 个人开始报数,报到 $m$ 的人出圈,然后从出圈的下一个人开始继续报数,直到圈中只剩下一人。求出该人的编号。

解法思路

采用数组法解决约瑟夫环问题,主要的思路是:构建一个大小为 $n$ 的数组,来表示 $n$ 个人在约瑟夫环中的位置,将这些位置依次删除,直到只有一个人为止。

具体的步骤如下:

  1. 定义一个大小为 $n$ 的数组 a,并初始化数组元素为 $1$ 表示这些人都还在约瑟夫环中。

  2. 定义一个变量 step,用来表示报数的步长。

  3. 定义一个变量 count,用来表示当前数到的位置。

  4. 定义一个变量 iIndex,用于记录出圈人的编号。

  5. 从第 $m$ 个人开始报数,即将变量 count 的初始值设置为 $m - 1$。

  6. 当数组 a 中的元素个数不为 $1$ 时,进行如下循环:

  7. count 的值加上 step - 1,即数到第 $m$ 个人所在的位置,再判断该位置是否为 $1$,如果是 $1$,则表示该人还在约瑟夫环中,继续往前数;如果不是 $1$,说明该人已经出圈,需要继续数,直到数到一个还在约瑟夫环中的人为止。

  8. 当找到下一个还在约瑟夫环中的人时,将其所在位置的数组元素置为 $0$,表示该人已经出圈。

  9. 记录该人的编号,即 iIndex 变量的值为当前所在位置 $+ 1$,因为数组下标从 $0$ 开始,编号从 $1$ 开始。

  10. count 变量加 $1$,表示从下一个人开始重新计数。

  11. 当数组 a 中的元素个数为 $1$ 时,剩下的那个人就是最后留下的人,输出其编号即可。

代码实现

以下是用 C 语言实现约瑟夫环问题(数组法)的完整程序代码,其中包括了两个示例,分别对应了题目中的两个例子:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int n = 5; // 5个人
    int m = 3; // 从第3个人开始报数
    int step = 2; // 报数步长为2

    // 初始化人员位置数组
    int* a = (int*)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        a[i] = 1;
    }

    // 初始化变量
    int count = 0;
    int iIndex = -1;

    // 开始报数
    while (1) {
        for (int i = 0; i < n; i++) {
            if (a[i] == 1) {
                count++;
                if (count == m) {
                    a[i] = 0; // 当前位置的人出圈
                    iIndex = i + 1; // 出圈人的编号
                    count = 0; // 重新开始报数
                }
            }
        }

        int iLeft = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] == 1) {
                iLeft++;
            }
        }

        if (iLeft == 1) {
            break; // 数组中只剩下一个人了
        }
    }

    printf("当 n = %d, m = %d, step = %d 时,最后出圈的人的编号是:%d\n", n, m, step, iIndex);
    free(a);

    n = 3; // 3个人
    m = 2; // 从第2个人开始报数
    step = 3; // 报数步长为3

    // 初始化人员位置数组
    a = (int*)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        a[i] = 1;
    }

    // 初始化变量
    count = 0;
    iIndex = -1;

    // 开始报数
    while (1) {
        for (int i = 0; i < n; i++) {
            if (a[i] == 1) {
                count++;
                if (count == m) {
                    a[i] = 0; // 当前位置的人出圈
                    iIndex = i + 1; // 出圈人的编号
                    count = 0; // 重新开始报数
                }
            }
        }

        int iLeft = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] == 1) {
                iLeft++;
            }
        }

        if (iLeft == 1) {
            break; // 数组中只剩下一个人了
        }
    }

    printf("当 n = %d, m = %d, step = %d 时,最后出圈的人的编号是:%d\n", n, m, step, iIndex);
    free(a);

    return 0;
}

示例说明

第一个示例中,有 $5$ 个人,从第 $3$ 个人开始报数,报数步长为 $2$,最后出圈的人的编号为 $5$。

第二个示例中,有 $3$ 个人,从第 $2$ 个人开始报数,报数步长为 $3$,最后出圈的人的编号为 $3$。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:约瑟夫环问题(数组法)c语言实现 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • va_list(),va_start(),va_arg(),va_end() 详细解析

    va_list(),va_start(),va_arg(),va_end() 详细解析 这四个函数在 C 语言中常用于对函数参数数量和类型不定的情况进行处理。下面将详细解析这四个函数。 va_list 它是 C 标准库中的一个类型,通常是一个指针,指向参数列表的起始位置。它用于存储从 va_start() 开始到参数列表最后一个参数数据地址的位置。 va_s…

    C 2023年5月23日
    00
  • C++文件读写操作详解

    先简单介绍一下C++中文件读写操作的基本概念: C++文件读写操作是指在C++程序中对计算机中的文件进行输入和输出的操作。文件读写操作是必不可少的C++编程操作之一,在文件读写操作中我们需要用到文件指针,读写位置指针,并且需要了解文件的打开、关闭、读写、复制等基本操作。C++文件操作通常使用C++标准库中的fstream头文件实现。下面介绍一些基本操作和示例…

    C 2023年5月22日
    00
  • C#实现的ACCESS数据库操作类完整实例

    下面我将详细讲解“C#实现的ACCESS数据库操作类完整实例”的完整攻略。 1. 准备工作 在使用C#操作ACCESS数据库之前,需要做以下准备工作: 安装ACCESS数据库驱动程序 在C#项目中添加对ACCESS数据库的引用 在代码中引入对System.Data.OleDb命名空间的引用 2. 创建ACCESS数据库连接对象 在开始对ACCESS数据库进行…

    C 2023年5月22日
    00
  • 实例代码分析c++动态分配

    关于“实例代码分析c++动态分配”的完整攻略,我给你提供以下的步骤: 步骤一:了解C++动态分配 在学习实例代码分析C++动态分配之前,我们首先需要了解什么是C++动态分配。C++的动态分配是指在程序运行期间动态地分配内存空间,这样可以更加灵活地管理内存,并且可以解决程序运行时因为内存不足而崩溃的问题。 比如,在C++中可以使用new和delete运算符来实…

    C 2023年5月23日
    00
  • C语言实现房屋管理系统

    C语言实现房屋管理系统攻略 1. 确定系统功能和数据结构 在实现房屋管理系统之前,需要确定系统需要实现的功能和数据结构。根据题目要求,系统需要实现以下功能: 用户登录/注册 添加房屋信息 修改房屋信息 删除房屋信息 查询房屋信息 而数据结构则需要存储房屋信息,包括: 房屋编号 房屋地址 房屋主人 房屋价格 是否出售/出租 因此,我们可以使用结构体来存储房屋信…

    C 2023年5月23日
    00
  • Code Review 方法论与实践总结梳理

    Code Review 方法论与实践总结梳理 什么是 Code Review Code Review 是通过代码检查,帮助团队确保代码质量、减少缺陷量、加快交付速度的过程。这是一个让其他开发者检查你的代码、找出问题、修改错误和提出建议的过程。它可以在项目中的任何阶段执行,也可以在多个阶段完成。 Code Review 的重要性 Code Review 旨在改…

    C 2023年5月22日
    00
  • C语言之sizeof与strlen的使用及区别

    当我们使用C语言进行编程时,有时需要知道变量或数组占用的内存大小,或者需要获取字符串的长度。这时就可以使用sizeof和strlen这两个函数。它们非常常用,但是很容易混淆,下面我将详细讲解它们的用法及区别。 一、sizeof的用法 sizeof是一个运算符,用于获取变量或类型的大小。它的语法如下: sizeof(变量或类型) 其中,变量或类型可以是任何类型…

    C 2023年5月23日
    00
  • C++实现多源最短路径之Floyd算法示例

    C++实现多源最短路径之Floyd算法示例 多源最短路径问题是指在给定图中任意两个顶点之间的最短路径问题。Floyd算法是解决该问题的一种经典算法,效率较低,但实现简单。 本篇文章将详细讲解如何使用C++语言实现Floyd算法,主要包含以下内容: 代码实现 算法详解 示例说明 代码实现 #include<iostream> using names…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部