C语言约瑟夫问题

有1至 N编号的N 个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始以正整数m作为报数上限值,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的报数上限值,从他的顺时针方向上的下一个人开始重新报数,如此下去,直至所有的人全部出列为止,要求产生记录出列顺序的表。如N = 7,每个人的密码依次是:3,1,7,2,4,8,4,m的值为20,则出列顺序为6,1,4,7,2,3,5。所有人用一个循环单链表表示,表中每个结点代表一个人,按出列次序依次将结点从循环单链表中删除,并按顺序存放在一个单链表中,链表的每个结点包括三个字段:code代表密码,no代表人的编号,link是指向下一个结点的指针。在主函数中,用堆分配的方法建立Josephus对象。循环展开对问题的求解。
在n个人的Josephus问题中,如果事先知道每个人的密码,求处于哪个位置,获胜的概率最大?

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>

typedef struct data//类型定义
{
int num;
int val;
}typedata;

typedef struct node
{
typedata data;
struct node *next;
}listnode;
typedef listnode *linklist;
linklist head;

void main()
{

int i,b,m,j,n;
char s1[100] ;char s2[100];char s3[100];
linklist head=(listnode *)malloc(sizeof(listnode));
listnode *p,*q;
loop1:printf("输入总人数[<100]:");
scanf("%s",s1);
for (i=0;s1[i]!='\0';i++)
{
if ((isdigit(s1[i]))!=0) continue;
else {printf("数据错误,请重新输入!\n");goto loop1;}
}
n=atoi(s1);
if (n>100||n<=0)
{
printf("输入数据不在范围之内,请重新输入!\n");
goto loop1;
}

else loop2:printf("请输入密码上限m[<100]:");
scanf("%s",s2);
for (i=0;s2[i]!='\0';i++)
{
if ((isdigit(s2[i]))!=0) continue;
else {printf("数据错误,请重新输入!\n");goto loop2;}
}
m=atoi(s2);
if (m>100||m<=0)
{
printf("输入数据不在范围之内,请重新输入!\n");
goto loop2;
}
q=head;

for(j=1;j<=n;j++)
{
loop3:printf("请输入第%d号同学的密码:",j);
scanf("%s",s3);
{for (i=0;s3[i]!='\0';i++)
{
if ((isdigit(s3[i]))!=0) continue;
else {printf("数据错误,请重新输入!\n");goto loop3;}
}
b=atoi(s3);
if (b>=m||b<=0)
{
printf("输入数据不在范围之内,请重新输入!\n");
goto loop3;
}}

q->next=(listnode *)malloc(sizeof(listnode));
q=q->next;
q->data.val=b;
q->data.num=j;
q->next=head->next;
}
printf("\n");
printf("结果顺序为:");
do{
i=1;
while(i!=m){
q=q->next;
i++;
}
p=q->next;
q->next=p->next;

printf(" %d",p->data.num,p->data.val);
m=p->data.val;
free(p);
}
while(q->next!=q);
printf(" %d",q->data.num,q->data.val);
free(q);
free(head);
printf("\n程序结束~\n");
}
温馨提示:内容为网友见解,仅供参考
第1个回答  2011-06-25
约瑟夫问题:
#include<iostream.h>
struct Node
{
int data;
Node *pNext;
};

void main()
{
int n,k,m,i;
Node *p,*q,*head;
cout<<"输入n的值:";
cin>>n;
cout<<"输入起始报数人号码k的值:";
cin>>k;
cout<<"输入 数到m出列的m的值:";
cin>>m;
head=(Node*)new Node; //确定头结点
p=head;
for(i=1;i<=n-1;i++) //赋初值
{
p->data=i;
p->pNext=(Node*)new Node; //为下一个新建内存
p=p->pNext;
}
p->data=n; //最后一个单独处理
p->pNext=head; //指向头,形成循环链表
p=head;

while(p->data!=(p->pNext)->data) //p->data==(p->pNext)->data表示只剩下一个结点的
{
while(p->data !=k) //寻找编号为k的结点
p=p->pNext;
if(m==1)
{
for(i=1;i<=n;i++)
{
cout<<p->data<<'\t' ;
p=p->pNext ;
}
cout<<'\n';
return;
}
else
for(i=1;i<m-1;i++) //开始报数
//找到报m-1的结点

q=p->pNext; //q为报m的结点
cout<<q->data<<"\t"; //输出报m的结点的值
k=(q->pNext)->data; //k为下一个报数的起点
p->pNext=q->pNext; //删除报m的结点
}
cout<<p->data<<'\n'; //输出最后一个结点的值
}
本回答被网友采纳
第2个回答  2011-06-23
这是我以前学c 语言是老师讲的例子:
/*约瑟夫环问题:编号为1,2,3…,n的n个人按顺时针方向围坐一圈,每人持有一个正整数密码。
一开始任选一个正整数m作为报数上限值,从第一个开始顺时针报数,报到m时停止,报m的人出列,
将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数;
如此下去,直到所有人全部出列为止。设计程序求出出列顺序。*/
#include <stdio.h>
#define N 1000
void main()
{
int a[N],i,m,count=0,baoshu=0,n;
printf("输入人数:");
scanf("%d",&n);
for(i=0;i<n;i++)
a[i]=i+1;
printf("请输入报数:");
scanf("%d",&m);
i=0;
while(count<n)
{
i++;
baoshu++;

if(a[i]!=0&&baoshu%m==0)
{
m=a[i];
count++;
printf("%4d出列",i);
a[i]=0;
baoshu=0;
}
if(i==n-1)
i=0;

}

}

//你说的获胜应该就是最后出来的吧。
第3个回答  2011-06-29
你好,我是吕秋云老师,你不用再找答案了,我已阅读了各大搜索引擎前500页的代码。发现雷同的一律0分处理;还是自己做好自己的编程实习吧

c语言解决约瑟夫问题
用c语言解决约瑟夫问题的方法如下:用单循环链表来解决这一问题,实现的方法首先要定义链表结点;单循环链表的结点结构与一般单链表的结点结构完全相同,只是数据域用一个整数来表示;将它们组成一个单循环链表。接下来从位置为1的结点开始数,数到第m的下一个结点,就将下一个结点从循环链表中删除;从...

约瑟夫环(单向循环链表)_C语言「抄作业」
在C语言抄作业系列中,提供了关于约瑟夫环问题的代码实现。该实现旨在解决Josephus与另一人最初位次的计算问题。作为一个计算机科学专业毕业多年后转行至产品经理的人,从当年的作业中搜集了这部分代码,供参考。

用C语言怎么编程,击鼓传花问题,求大神
这是一个经典的约瑟夫问题,用于解决“击鼓传花”类问题。提供以下C语言程序参考。代码如下:c include define N 30 int yuesefu1(int data[],int sum,int k) { int i=0,j=0,count=0;while(count { if(data[i]!=0) j ;if(j==k) { data[i]=0;count ;j=0;} i ;if(i==sum...

C语言-有趣的约瑟夫问题及解决办法
约瑟夫问题的数学解决方案多种多样,这里提供一种使用循环链表的方法。此方法基于原始问题中的圆圈排列,通过循环链表实现数人与淘汰的过程。编写一个程序,根据特定规则运行,即可模拟出约瑟夫问题的解。程序源代码如下,通过调整Start、Count、length这三个参数,可以改变游戏规则,尝试不同的初始位置和人数。...

C语言编程丨循环链表实现约瑟夫环!真可谓无所不能的C!
约瑟夫环问题是一个经典的应用场景,描述了在一定规则下的淘汰机制。该问题的基本设定是 n 个人围坐在圆桌周围,从指定编号开始,按照特定规则进行淘汰,直到仅剩一人。循环链表是实现该问题的关键结构。考虑一个示例场景:假设圆桌上有 5 人,从编号为 3 的人开始,每数到 2 的人数淘汰一人。具体流程...

基于C语言 实现圆桌问题
圆桌问题也就是约瑟夫问题。1、约瑟夫问题:Joseph问题的一种描述是:编号为1、2、……、n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他...

约瑟夫问题约瑟夫"密码问题"
要解决这个问题,你需要编写一个C语言程序。程序的核心步骤包括接收用户输入的N值和初始的M值,以及每个人的密码。然后,通过一个循环结构模拟报数过程,每当报数到M时,更新M的值并更新报数顺序。在每次循环中,都需要检查当前编号的人是否应该被淘汰,如果是,则更新圈内人数和报数顺序,直到所有人出列...

用C语言解决一个实际问题(不要太长)
约瑟夫环(很有名的数学问题)已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。void JOSEPHUS(int n,int k,int m) \/\/n为总人数,k...

数据结构中的约瑟夫环问题用C语言怎么编写出来啊?
圈子,问最后留下的是原来第几号的那位。1. 程序分析:这是一个比较经典的算法--约瑟夫环问题.2.个人分析: 算法比较经典,对于这样的问题本应该使用链表的形式会比较容易.约瑟夫环算法 则体现了使用数组来完成链表该完成的功能,虽然形式上完全不相同,但却求出了 相同的结果.有异曲同工之妙.总之我...

C语言做约瑟夫环问题要注意哪些问题
1,查找到的位置,要做标记,以便下次不会再重复。删除或是移出队列 2,查找到最后的一个位置后,要从开始再计数。注意不能超越下标,或是访问非法结点。3,有多个元素(X),就要循环X-1次,以保证最后结果个数的正确性。

相似回答