背景:
约瑟夫环(Josephus)问题是由古罗马的史学家约瑟夫(Josephus)提出的,他参加并记录了公元66—70年犹太人反抗罗马的起义。约瑟夫作为一个将军,设法守住了裘达伯特城达47天之久,在城市沦陷之后,他和40名死硬的将士在附近的一个洞穴中避难。在那里,这些叛乱者表决说“要投降毋宁死”。于是,约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的。约瑟夫有预谋地抓到了最后一签,并且,作为洞穴中的两个幸存者之一,他说服了他原先的牺牲品一起投降了罗马。
约瑟夫环问题的具体描述是:设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。
代码:
#include<stdio.h>
#include<malloc.h>
struct Node{
int number; //num存储序号,pass存储密码
int password;
struct Node *next;
};
Node *creat(int n, int a[]) { //实现环的建立,并输入每个人的密码
int i = 1;
Node *head; //链表头指针
Node *p; //链表当前节点
Node *q; //链表新插入的节点
p = (struct Node *)malloc(sizeof(struct Node));
p->number = i;
p->password = a[i - 1];
head = p;
for (i = 2; i <= n; ++i) {
q = (struct Node *)malloc(sizeof(struct Node));
q->number = i;
q->password = a[i - 1];
p->next = q; //连接链表与新创建的节点
p = q;
}
p->next = head; //形成环
return head;
}
void F(Node *head, int len, int password){
Node *pre; //pre指向t前一个
Node *t; //出列的节点
pre = head;
for (int i = 1; i < len; ++i) { //将pre节点移动至尾部
pre = pre->next;
}
for (int i = 1; i <= len; ++i) {
for (int j = 1; j < password; ++j) {
pre = pre->next; //将pre指针移动到出列的前一个
}
t = pre->next; //指向要删除的节点
password = t->password;
printf("%3d",t->number);
pre->next = t->next; //连接链表
free(t); //释放该节点
}
}
int main() {
int len; //环的长度
printf("输入约瑟夫环的长度:");
scanf("%d",&len);
int a[len];
printf("请输入的初始密码 m: ");
int m;
scanf("%d",&m);
printf("请输入每个人的密码: ");
for (int i = 0; i < len; ++i) {
scanf("%d",&a[i]);
}
Node *head = creat(len, a);
F(head, len, m);
return 0;
}
运行结果:
欢迎大家来阅读我的文章,后续我会更新更多计算机相关大作业,数据结构,计组,操作系统,计网,都会更新,换欢迎大家来关注我,有作业相关问题的也可以私聊我,感谢大家的关注,评论。