约瑟夫环
问题描述
约瑟夫问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始。按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计程序求出出列顺序。
基本要求
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。
测试数据m的初值为20;密码: 3,1,7,2,4,8,4。(正确的结果应为6,1,4,7,2,3,5)
实现提示
程序运行后首先要求用户指定初始报数上限值,然后读取各人的密码。
选作内容
向上述程序中添加在顺序结构上实现的部分。
#include <stdio.h>
struct node {
int data; //密码
int number; //编号
int nextidx; //下一个位置
}list[1005];
int daa;
int delete(int da, int num) {
int k = num;
for (int i = 1; i < da; ++i) {
k = list[k].nextidx; //遍历约瑟夫环,寻找删除位置
}
daa=list[list[k].nextidx].data; //记录下一轮的m
printf("%d ",list[list[k].nextidx].number); //打印结果
list[k].nextidx = list[list[k].nextidx].nextidx; //删除操作
return k; //返回下一轮开始位置的前一个位置
}
int main() {
int n;
scanf("%d", &daa); //标记初始值
scanf("%d", &n); //读入人数上限
for (int i = 1; i <= n; ++i) {
scanf("%d", &list[i].data); //读入每个人的密码
list[i].number = i; //初始化每个人的编号
list[i].nextidx = i + 1; //标记每个人的后一个人的位置
}
list[n].nextidx = 1; //最后一个人的后一个人的位置为第一个人的位置
int sum = n; //记录人数数量
int q = n; //标记下一轮开始位置的前一个位置,便于删除
while (sum--) {
q = delete(daa, q); //删除操作
}
printf("\n");
return 0;
}