约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
题解:(部分注释由通义生成)
#include <myhead.h>
// 定义链表节点结构体
typedef struct Node
{
int data;
struct Node *next;
} Node, *pnode;
pnode Create()
{
pnode head; // 头节点指针
head = (pnode)malloc(sizeof(Node)); // 动态分配内存给头节点
if (head == NULL)
exit(1); // 如果内存分配失败,则退出程序
head->next = NULL; // 头节点的next指针指向空,表示链表初始为空
return head; // 返回头节点指针
}
int main()
{
int i, m, n; // 定义变量
pnode tail, add, kill, slow; // 定义链表指针变量
pnode head = Create(); // 创建链表
printf("输入总人数和淘汰数字"); // 提示用户输入总人数和淘汰数字
scanf("%d %d", &n, &m); // 读取用户输入
// 判断输入是否合法
if (n == 0 || m == 0)
{
return 0; // 如果输入为0,则结束程序
}
else // 初始化整个链表
{
tail = head; // 尾指针初始化为头指针
for (i = 0; i < n; i++) // 循环n次,添加n个节点
{
add = (pnode)malloc(sizeof(Node)); // 动态分配内存给新节点
if (add == NULL)
{
printf("申请失败!");
exit(1); // 如果内存分配失败,则提示错误并退出程序
}
add->data = i + 1; // 设置新节点的数据为i+1
tail->next = add; // 尾节点的next指向新节点
add->next = head->next; // 新节点的next指向头节点的next,形成环形链表
tail = add; // 更新尾指针为新节点
}
}
// kill为要淘汰的节点,slow为慢指针
kill = head->next;
slow = tail;
i = 1; // 初始化计数器i
// 当淘汰指针kill不等于慢指针slow时,执行循环
while (kill != slow)
{
if (i == m) // 如果计数器i等于淘汰数字m
{
slow->next = kill->next; // 淘汰kill节点,修改慢指针的next
printf("淘汰%d\t", kill->data); // 输出被淘汰的数字
free(kill); // 释放淘汰的节点内存
kill = slow->next; // 更新淘汰指针为下一个待淘汰节点
i = 1;
}
else
{
slow = kill; // 更新慢指针
kill = slow->next; // 更新淘汰指针
i++;
}
}
printf("\n最终数字%d\n", kill->data); // 输出最后剩下的数字
return 0;
}
195

被折叠的 条评论
为什么被折叠?



