问题描述:
约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的,我们把问题描述如下:
- 现有T个人围成一桌坐下,编号从1到T,从编号为1的人开始报数。
- 报数也从1开始,报到M的人离席,从离席者的下一位在座成员开始,继续从1开始报数。
- 复现这个过程(各成员的离席次序),或者求最后一个在座的成员编号。
代码实现
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
int main() {
int m, n;
printf("请输入人数m和需要报数的间隔n:");
scanf("%d,%d", &m, &n);
Node* head = NULL;
Node* tail = NULL;
// 创建循环链表
for (int i = 1; i <= m; i++) {
Node* p = (Node*)malloc(sizeof(Node));
p->data = i;
if (head == NULL) {
head = p;
head->next = head; // 第一个节点的 next 指向自身,形成循环
tail = head;
}
else {
tail->next = p;
p->next = head;
tail = p;
}
}
if (head == NULL || m <= 0) {
printf("链表为空。\n");
return 0;
}
Node* current = head;
Node* prev = NULL; // 修改起始节点为尾节点
// 找到需要删除的节点,并删除,直到链表只剩下一个节点
while (m!=2) {
// 移动到要删除的节点的前一个节点
for (int i = 0; i < n - 1; i++) {
prev = current;
current = current->next;
}
// 删除节点
prev->next = current->next;
Node* temp = current;
current = current->next;
m--;
free(temp);
}
printf("最后剩下的人的序号为:%d\n", current->data);
// 释放最后剩下的节点
free(current);
return 0;
}