第五题:约瑟夫环
实验题目
给定100个人站成一圈,从第1个人开始依次报数。
每数到3的人将会被淘汰,然后继续从下一个人开始报数。
这个过程会一直持续,直到所有的人都被淘汰。
请编写一个C语言程序来模拟这个过程,并且输出每一个被淘汰人的编号。
要求:输出每一个被淘汰人的编号,每淘汰一个人输出一行,格式为:"%d out \n"(每输出一次换行)
实验要求
- 模拟约瑟夫环:程序需要模拟100个人围成一圈,从第1个人开始报数,每数到3的人被淘汰的过程。
- 输出淘汰顺序:程序需要输出每一个被淘汰人的编号,每淘汰一个人输出一行,格式为:
"%d out \n"
。
实验代码框架
// 05_josephus_ring.c
#include <stdio.h>
/**
* 给定100个人站成一圈,从第1个人开始依次报数。
* 每数到3的人将会被淘汰,然后继续从下一个人开始报数。
* 这个过程会一直持续,直到所有的人都被淘汰。
* 请编写一个C语言程序来模拟这个过程,并且输出每一个被淘汰人的编号。
* 要求:输出每一个被淘汰人的编号,每淘汰一个人输出一行,格式为:"%d out \n"(每输出一次换行)
*/
#define ALL_NUM 100
#define COUNT_NUM 3
#define OUT_NUM 3
/* people id array such as (1,2,3,4,5,6) */
int people[ALL_NUM];
int main(void)
{
int left; /* 剩余人数 */
int pos; /* 当前报数位置 */
int step; /* 当前报数 */
//TODO
return 0;
}
实验解析
代码实现
#include <stdio.h>
#define ALL_NUM 100 // 总人数
#define COUNT_NUM 3 // 报数到3的人被淘汰
#define OUT_NUM 3 // 淘汰的数字
int people[ALL_NUM]; // 人员编号数组
int main(void)
{
int left = ALL_NUM; // 剩余人数
int pos = 0; // 当前报数位置
int step = 0; // 当前报数
while (left > 0)
{
// 模拟报数
step++;
if (step == COUNT_NUM)
{
// 输出被淘汰的人的编号
printf("%d out\n", people[pos] + 1);
// 淘汰这个人
for (int i = pos; i < left - 1; i++)
{
people[i] = people[i + 1];
}
left--;
step = 0; // 重置报数
}
// 移动到下一个人
pos = (pos + 1) % left;
}
return 0;
}
代码解释
- 初始化:定义了总人数
ALL_NUM
,淘汰数字COUNT_NUM
,以及一个数组people
来存储每个人的编号。 - 模拟报数:使用一个循环来模拟报数过程,直到所有人都被淘汰。
- 报数和淘汰:
step
变量用于记录当前报数,当step
等于COUNT_NUM
时,表示当前报数的人应该被淘汰。此时,输出该人的编号,并从数组中移除这个人,然后重置step
。 - 移动到下一个人:使用
pos = (pos + 1) % left
来移动到下一个人,这里使用了取模运算来保证在数组长度变化时,pos
始终指向有效的位置。