C语言 循环链表 约瑟夫问题

这篇博客介绍了如何使用C语言通过循环链表解决约瑟夫问题,这是ecnu数据结构月考的一道题目。博主分享了自己的学习过程,并希望对他人有所帮助。
摘要由CSDN通过智能技术生成

ecnu数据结构月考题:

循环链表解决约瑟夫问题

题目不是很难啦,单纯记录一下自己学习的足迹。
如果对于需要的人能有帮助,那真是再好不过了嘻嘻♪(・ω・)ノ

题目

在这里插入图片描述
在这里插入图片描述

代码

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

struct node{
   
    int name;
    struct node*next;
    };

int main()
{
   
    int n,m;
    struct node*head =(struct node*
约瑟夫问题是一个经典的数学问题:n个人围成一圈,从第1个人开始报数,报到m的人出圈,然后从出圈的下一个人开始重新报数,直到剩下最后一个人。现在用C语言实现循环链表来解决这个问题。 首先,我们需要定义一个循环链表节点的结构体: ```c typedef struct node { int num; // 编号 struct node *next; // 指向下一个节点的指针 } Node; ``` 接下来,我们需要编写一个函数来创建一个包含n个节点的循环链表: ```c Node *createList(int n) { Node *head = malloc(sizeof(Node)); // 创建头节点 head->num = 1; head->next = NULL; Node *tail = head; // 尾指针指向头节点 for (int i = 2; i <= n; i++) { Node *node = malloc(sizeof(Node)); // 创建新节点 node->num = i; node->next = NULL; tail->next = node; // 尾节点的next指针指向新节点 tail = node; // 尾指针指向新节点 } tail->next = head; // 尾节点的next指针指向头节点,形成循环链表 return head; } ``` 接着,我们需要编写一个函数来解决约瑟夫问题。该函数接受三个参数:循环链表的头节点、起始报数的位置和出圈的数字m。 ```c void josephus(Node *head, int start, int m) { Node *p = head; while (p->num != start) { p = p->next; // 找到起始位置的节点 } while (p->next != p) { for (int i = 1; i < m; i++) { p = p->next; // 报数 } printf("%d ", p->num); // 输出出圈的数字 Node *q = p->next; p->num = q->num; // 将下一个节点的编号赋给当前节点,相当于删除了下一个节点 p->next = q->next; // 删除下一个节点 free(q); // 释放下一个节点的内存 } printf("%d ", p->num); // 输出最后一个数字 } ``` 最后,我们可以在main函数中调用上述函数来解决约瑟夫问题: ```c int main() { int n, start, m; printf("请输入n, start, m: "); scanf("%d%d%d", &n, &start, &m); Node *head = createList(n); josephus(head, start, m); return 0; } ``` 完整代码如下: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int num; // 编号 struct node *next; // 指向下一个节点的指针 } Node; Node *createList(int n) { Node *head = malloc(sizeof(Node)); // 创建头节点 head->num = 1; head->next = NULL; Node *tail = head; // 尾指针指向头节点 for (int i = 2; i <= n; i++) { Node *node = malloc(sizeof(Node)); // 创建新节点 node->num = i; node->next = NULL; tail->next = node; // 尾节点的next指针指向新节点 tail = node; // 尾指针指向新节点 } tail->next = head; // 尾节点的next指针指向头节点,形成循环链表 return head; } void josephus(Node *head, int start, int m) { Node *p = head; while (p->num != start) { p = p->next; // 找到起始位置的节点 } while (p->next != p) { for (int i = 1; i < m; i++) { p = p->next; // 报数 } printf("%d ", p->num); // 输出出圈的数字 Node *q = p->next; p->num = q->num; // 将下一个节点的编号赋给当前节点,相当于删除了下一个节点 p->next = q->next; // 删除下一个节点 free(q); // 释放下一个节点的内存 } printf("%d ", p->num); // 输出最后一个数字 } int main() { int n, start, m; printf("请输入n, start, m: "); scanf("%d%d%d", &n, &start, &m); Node *head = createList(n); josephus(head, start, m); return 0; } ```
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值