用C语言:有n个人围成一圈,顺序排号。从第1个人开始1—3报数,凡报到3的人退出圈子,问最后留下的是原来第几号的那位
时间: 2023-11-23 21:24:06 浏览: 129
可以使用循环链表来模拟这个过程,每个节点表示一个人,节点中保存该人的编号和是否已经退出圈子的标记。具体实现如下:
```c
#include <stdio.h>
#include <stdlib.h>
// 循环链表节点
typedef struct Node {
int num; // 编号
int out; // 是否已经退出圈子
struct Node* next; // 下一个节点
} Node;
// 初始化循环链表
Node* initList(int n) {
Node* head = (Node*)malloc(sizeof(Node));
head->num = 1;
head->out = 0;
Node* cur = head;
for (int i = 2; i <= n; i++) {
Node* node = (Node*)malloc(sizeof(Node));
node->num = i;
node->out = 0;
cur->next = node;
cur = node;
}
cur->next = head; // 将链表首尾相连,形成循环链表
return head;
}
// 模拟报数过程
int countOff(Node* head, int k) {
Node* cur = head;
int count = 1; // 当前报数的人的编号
while (head->next != head) { // 只要链表中还有两个及以上的节点,就继续报数
if (!cur->out && count % 3 == 0) { // 如果该人还没有退出圈子,并且报数到3了
cur->out = 1; // 标记该人已经退出圈子
k--; // 退出圈子的人数减1
if (k == 0) { // 如果已经退出k个人了,直接返回最后留下的人的编号
return cur->num;
}
}
if (!cur->out) { // 如果该人还没有退出圈子
count++; // 报数加1
}
cur = cur->next; // 移动到下一个节点
}
return head->num; // 最后剩下的一个人的编号
}
int main() {
int n, k;
printf("请输入n和k:");
scanf("%d%d", &n, &k);
Node* head = initList(n);
int num = countOff(head, k);
printf("最后留下的是原来第%d号的那位\n", num);
return 0;
}
```
需要注意的是,循环链表的头结点也要参与报数,因此在 `countOff` 函数中需要用一个变量 `count` 来记录当前报数的人的编号。另外,循环链表中的节点需要在程序结束时释放,以免内存泄漏。
阅读全文