实验名称:约瑟夫环 问题描述:约瑟夫环问题的一种描述是:编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。 基本要求:利用单向循环链表模拟此过程,按照出列的顺序印出各人的编号。 测试数据:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,首先m值为6(正确的出列顺序应为6,1,4,7,2,3,5)。 实现提示:程序运行后,首先要求用户指定初始报数上限值,然后读取各人的密码。可设n<=30。此题所用的循环链表中不需要头结点,注意空表和非空表的界限。
时间: 2023-05-28 09:08:10 浏览: 89
实验一:约瑟夫环.cpp
实现思路:
1.首先定义一个结构体表示每个人,包括编号和密码;
2.根据输入的人数n,创建n个结构体,分别表示每个人,将它们按顺序连接成一个单向循环链表;
3.定义一个指针p指向链表的头结点,然后开始模拟报数的过程;
4.在循环中,先找到报数为m的人,将其从链表中删除,并输出其编号;
5.然后将其密码作为新的m值,继续从下一个人开始报数;
6.重复以上步骤,直到链表为空,即所有人都已出列。
代码实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int id; // 编号
int password; // 密码
struct Node *next; // 指向下一个节点的指针
} Node;
int main() {
int m, n, i;
Node *p, *q, *head;
// 输入初始报数值m和人数n
printf("请输入初始报数值m和人数n:");
scanf("%d%d", &m, &n);
// 创建一个循环链表,表示n个人,每个人有一个密码
head = (Node*)malloc(sizeof(Node)); // 创建头结点
p = head;
for (i = 1; i <= n; i++) {
q = (Node*)malloc(sizeof(Node)); // 创建新节点
q->id = i;
printf("请输入第%d个人的密码:", i);
scanf("%d", &(q->password));
p->next = q; // 将新节点连接到链表尾部
p = q;
}
p->next = head->next; // 将链表首尾相连,形成循环链表
// 模拟报数的过程
p = head->next;
printf("出列顺序:");
while (p != p->next) { // 当链表中只剩一个节点时结束循环
for (i = 1; i < m; i++) { // 报数
q = p;
p = p->next;
}
q->next = p->next; // 将p指向的节点从链表中删除
printf("%d ", p->id); // 输出出列的人的编号
m = p->password; // 将出列的人的密码作为新的m值
free(p); // 释放出列的节点的内存空间
p = q->next; // 从下一个人开始报数
}
printf("%d\n", p->id); // 输出最后一个出列的人的编号
// 释放链表的头结点的内存空间
free(head);
return 0;
}
阅读全文