重新用c语言写一下约瑟夫环问题
时间: 2023-10-13 18:06:47 浏览: 93
好的,以下是用C语言写的约瑟夫环问题代码:
```c
#include <stdio.h>
int josephus(int n, int k) {
if (n == 1) {
return 1;
} else {
// 对于圆环长度为 n 的情况,最后剩下的数字在圆环长度为 n-1 时的位置为 f(n-1,k)
// 由于每次删除数字后,圆环长度减一,因此需要将得到的位置加上 k-1,最后对圆环长度取模
return (josephus(n - 1, k) + k - 1) % n + 1;
}
}
int main() {
int n, k;
printf("请输入圆环长度n和每次数k:");
scanf("%d%d", &n, &k);
printf("最后剩下的数字为:%d\n", josephus(n, k));
return 0;
}
```
在主函数中,通过 `scanf` 函数获取用户输入的圆环长度 `n` 和每次数 `k`,然后调用 `josephus` 函数计算最后剩下的数字,并输出结果。
在 `josephus` 函数中,使用递归的方式求解,在圆环长度为 1 时返回 1,否则根据递推式 `f(n,k)=[f(n-1,k)+k-1]%n+1` 计算最后剩下的数字在当前圆环长度下的位置。
相关问题
用c语言解释一下约瑟夫环问题
约瑟夫环问题是一个经典的问题,描述如下:有n个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,直到剩下最后一个人。现在给定n和m,求最后剩下的人的编号。
以下是两种用C语言解决约瑟夫环问题的方法:
1. 递归法
```c
/* 用递归解决约瑟夫环问题 n指的是总人数,m指的是每次最大报到的数值,i是第i次,该函数每次可以求出第i次扔海里的人的编号 */
int Algo3(int n,int m,int i){
if(i==1) return (n+m-1)%n;
else return (Algo3(n-1,m,i-1)+m)%n;
}
void main(){
int n=5; //假设5个人围坐一圈
int m=2; //数到2的那个人出环
printf("假设第一次从编号为1的人开始数,数到%d的那个人出环\n",m);
for(int i=1;i<=n;i++)
printf("第%d次出环的元素是%d\n",i,Algo3(n,m,i)+1); //因为求出的结果是数组中的下标,最终的编号还要加1
}
```
2. 迭代法
```c
/* 用迭代解决约瑟夫环问题 递推公式: f(N,M)=(f(N−1,M)+M)%N f(N,M)表示,N个人报数,每报到M时杀掉那个人,最终胜利者的编号 f(N−1,M)表示,N-1个人报数,每报到M时杀掉那个人,最终胜利者的编号 */
int Algo4(int n,int m){
int i,p=0;
for(i=2;i<=n;i++){
p=(p+m)%i;
}
return p+1; //因为求出的结果是数组中的下标,最终的编号还要加1
}
void main(){
int n=5; //假设5个人围坐一圈
int m=2; //数到2的那个人出环
printf("假设第一次从编号为1的人开始数,最后出环的是:%d\n",Algo4(n,m));
}
```
用c语言写约瑟夫环问题
约瑟夫环问题是一个经典的数学问题,它有很多种解法,其中一种比较常见的解法是使用链表来模拟环形结构。下面是一个用 C 语言实现的例子:
```c
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
Node *createList(int n) {
Node *head = NULL, *p = NULL, *prev = NULL;
int i;
for (i = 1; i <= n; i++) {
p = (Node *) malloc(sizeof(Node));
p->data = i;
if (prev != NULL) {
prev->next = p;
} else {
head = p;
}
prev = p;
}
prev->next = head;
return head;
}
void printList(Node *head) {
Node *p = head;
do {
printf("%d ", p->data);
p = p->next;
} while (p != head);
printf("\n");
}
void josephus(int n, int m) {
Node *head = createList(n);
Node *p = head, *prev = NULL;
int i;
for (i = 1; i < m; i++) {
prev = p;
p = p->next;
}
while (n > 0) {
printf("%d ", p->data);
prev->next = p->next;
free(p);
p = prev->next;
n--;
if (n > 0) {
for (i = 1; i < m; i++) {
prev = p;
p = p->next;
}
}
}
printf("\n");
}
int main() {
josephus(7, 3);
return 0;
}
```
该程序中,`createList` 函数用于创建一个包含 `n` 个节点的循环链表,并返回链表的头节点。`printList` 函数用于打印链表中的所有元素。`josephus` 函数用于解决约瑟夫环问题,其中 `n` 表示总人数,`m` 表示每次报数的人数。程序通过遍历链表来模拟约瑟夫环,每次找到第 `m` 个人,并将其从链表中删除,直到所有人都被删除为止。
以上是一种较为简单的解法,如果需要提高程序的效率,可以使用数组来模拟循环队列或者使用数学公式来计算出最后剩下的人的编号。
阅读全文