有n个人围成一圈,顺序排号。从第1个人开始1—3报数,凡报到3的人退出圈子,问最后留下的是原来第几号的那位,并记录每一个淘汰的人是在第几圈被淘汰的。编写c语言程序,完成上述
时间: 2023-12-27 22:18:21 浏览: 74
问题的求解。
好的,这是一个经典的约瑟夫问题。我们可以使用循环链表来模拟这个过程,每次找到要被淘汰的结点,将其从链表中删除,直到只剩下最后一个结点为止。以下是完整的C语言程序实现:
```c
#include <stdio.h>
#include <stdlib.h>
// 定义链表结点类型
typedef struct Node {
int num; // 编号
int round; // 淘汰轮数
struct Node *next; // 指向下一个结点
} Node;
// 初始化循环链表,n为结点个数
Node *initList(int n) {
Node *head = (Node *)malloc(sizeof(Node));
head->num = 1;
head->round = 0;
head->next = NULL;
Node *prev = head;
for (int i = 2; i <= n; i++) {
Node *node = (Node *)malloc(sizeof(Node));
node->num = i;
node->round = 0;
node->next = NULL;
prev->next = node;
prev = node;
}
prev->next = head; // 将链表收尾相连,形成循环链表
return head;
}
// 打印链表中所有结点的编号和淘汰轮数
void printList(Node *head) {
Node *node = head;
do {
printf("编号:%d,淘汰轮数:%d\n", node->num, node->round);
node = node->next;
} while (node != head);
}
// 模拟淘汰过程,m为报数上限
int josephus(int n, int m) {
Node *head = initList(n); // 初始化链表
Node *prev = head;
Node *node = head->next;
int count = 1;
while (head->next != head) {
if (count == m) {
prev->next = node->next; // 从链表中删除当前结点
printf("第%d个人在第%d轮被淘汰\n", node->num, node->round + 1);
count = 1;
node->round++; // 记录淘汰轮数
node = prev->next;
} else {
prev = node;
node = node->next;
count++;
}
}
printf("最后留下的是原来第%d号的那位\n", head->num);
return head->num;
}
int main() {
int n, m;
printf("请输入人数n和报数上限m:");
scanf("%d %d", &n, &m);
josephus(n, m);
return 0;
}
```
运行程序,输入人数n和报数上限m后,程序会输出每个被淘汰的人的编号和淘汰轮数,以及最后留下的人的编号。
阅读全文