C语言设有n 个人围坐在一个圆桌周围,编号顺序从1到n。现从第s个人开始报数,数到m 的 人出列,然后从出列的下一个人重新开始报数,数到 m 的人又出列。如此重复直到所有的人 全部出列为止。对于任意给定的n,s和m,输出按出列次序得到的n 个人员的编号。 输入 三个空格分隔的整数n,s和m,其中1≤n,m≤102,1≤s≤n 。 输出 输出n 行,表示n 个人的出列序列。
时间: 2023-06-27 07:02:24 浏览: 135
约瑟夫问题 设有N个人围坐一圈,现从某人开始报数, 数到M的人出列,接着从出列的下一个人重新报数,数到M的人又出列,如此下去直到所有人都出列为止,试给出他们的出列次序
3星 · 编辑精心推荐
这是一个经典的约瑟夫问题,可以用循环链表来解决。具体做法如下:
1. 创建一个循环链表,链表节点的值为人员编号 1~n。
2. 把链表的最后一个节点指向第一个节点,形成一个循环链表。
3. 从第s个节点开始遍历链表,数到m就删除该节点,重复此操作直到链表中只剩下一个节点。
4. 输出每次删除的节点的值即为按出列次序得到的n个人员的编号。
以下是代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int val;
struct Node *next;
} Node;
// 创建循环链表
Node* createList(int n) {
Node *head = (Node *)malloc(sizeof(Node));
head->val = 1;
head->next = NULL;
Node *cur = head;
for (int i = 2; i <= n; i++) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->val = i;
newNode->next = NULL;
cur->next = newNode;
cur = newNode;
}
cur->next = head; // 链表的最后一个节点指向第一个节点,形成循环链表
return head;
}
// 删除节点
Node* deleteNode(Node *pre, Node *cur) {
pre->next = cur->next;
Node *next = cur->next;
free(cur);
return next;
}
// 按出列次序得到的n个人员的编号
void printList(Node *head) {
Node *cur = head;
while (cur->next != head) {
printf("%d\n", cur->val);
cur = cur->next;
}
printf("%d\n", cur->val); // 输出最后一个节点
}
int main() {
int n, s, m;
scanf("%d %d %d", &n, &s, &m);
Node *head = createList(n);
Node *cur = head;
for (int i = 1; i < s; i++) { // 找到第s个节点
cur = cur->next;
}
while (cur->next != cur) { // 循环遍历链表直到只剩下一个节点
for (int i = 1; i < m; i++) { // 数到m
cur = cur->next;
}
cur = deleteNode(cur, cur->next); // 删除节点
}
printList(cur); // 输出按出列次序得到的n个人员的编号
return 0;
}
```
阅读全文