瑟夫环问题

MZJCDD 2008-03-24 12:40:30
题目是50是个人站在一圈,依次编号1,2,3,......50.第一个人开始数数1,2,3 到3的人推出来 第四个人接着数1,2,3 这样下去 。直到剩下一个人,问剩下的这个人是原来的多少号?我的程序是下面:
#include<stdio.h>
#include<malloc.h>
#define NULL 0
#define LEN sizeof(struct student)
struct student
{int num;
struct student *next;
};
struct student *creat(void)
{struct student *head ,*p1,*p2;
int n,i;
p1=p2=(struct student *)malloc(LEN);
i=1;n=0;
p1->num=i;
head=NULL;
while(p1->num<=50)
{n++;
if(n==1)head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct student *)malloc(LEN);
p1->num=++i;
}
p2->next=head;
return(head);
}
struct student *del(struct student *head,int num)
{struct student *p1,*p2;int i,n;
do
{if(n==50)p1=head;
else p1=p1->next;

for(i=0;i<=2;i++)
{p2=p1;
p1=p1->next;
}
p2->next=p1->next;
n--;
}
while(n>1);
return(head);
}
void main()
{struct student *p;
p=del(creat(),50);
if(p!=NULL)
do
{printf("%d",p->num);
p=p->next;
}
while(p!=NULL);
}
不知道是哪里有问题,就是运行不出来结果
有哪位高手,请指点。

...全文
390 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
maimang09 2010-03-27
  • 打赏
  • 举报
回复
thinking it's beyond me!
xrainfir 2008-07-10
  • 打赏
  • 举报
回复
lz能把程序写的这么复杂...
堂积Code 2008-07-10
  • 打赏
  • 举报
回复
看看这个:
#include<stdio.h>
int main(){
int i,k=1,j=0,a[51];
for(i=0;i<=50;i++)
a[i]=i;
while(j!=1){
for(i=0;i<=50;i++){
if(a[i]!=0){
if(k<3){
k++;
}else
a[i]=0;
k=1;
}}}
for(i=0,j=0;i<=50;i++){
if(a[i]!=0){
j++;
}}
}
i=0;
while(a[i]==0)
i++;
printf("%d\n",i);
return 0;
}
开始
for循环赋值
while
wangboqun99 2008-07-09
  • 打赏
  • 举报
回复
System.out.printf是那个语言的输出格式啊?
JAVA or C?
s79947171 2008-07-08
  • 打赏
  • 举报
回复
不好意思时间紧就用java写了个思想是一样的,电脑坏了由记事本写的所以难免有错误!请楼主自己改正一下
class Test{
boolean flag=true;//标记
int count=0;//计数
int sum=1;//出具人数
int num[50];
for(int i=0;i<50;i++){//数组赋值
num[i]=flag;//初始都为真
}
for(int k=0;k<50;k++){
if(num[k]){
count++;
if(count==3){
num[k]=false;
sum++;
count=0;
if(sum==49){
break;
}
}
}
if(k==49){//便利一遍后从头继续开始
k=0;
}
}
for(int i=0;i<50;i++){
if(num[i]){
System.out.printf("最后剩下人的位置为"+(i+1));
}
}
}
s79947171 2008-07-08
  • 打赏
  • 举报
回复
上面的有点问题更正一下
class Test{
boolean flag=true;//标记
int count=0;//计数
int sum=0;//出具人数
int num[50];
for(int i=0;i <50;i++){//数组赋值
num[i]=flag;//初始都为真
}
for(int k=0;k <50;k++){
if(num[k]){
count++;
if(count==3){
num[k]=false;
sum++;
count=0;
if(sum==49){
break;
}
}
}
i++;
if(k==50){//便利一遍后从头继续开始
k=0;
}
}
for(int i=0;i <50;i++){
if(num[i]){
System.out.printf("最后剩下人的位置为"+(i+1));
}
}
}
结果为436
meiZiNick 2008-05-01
  • 打赏
  • 举报
回复
接分是王道!
knowledge_Is_Life 2008-05-01
  • 打赏
  • 举报
回复
有点难度哦
laolaoliu2002 2008-03-24
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<stdlib.h>

#define MAX_NODE_NUM 30
#define TRUE 1U
#define FALSE 0U

typedef struct NodeType
{ int id; /* 编号 */
int cipher; /* 密码 */
struct NodeType *next;
} NodeType;

/* 创建单向循环链表 */
static void CreaList(NodeType **, const int);
/* 运行"约瑟夫环"问题 */
static void StatGame(NodeType **, int);
/* 打印循环链表 */
static void PrntList(const NodeType *);
/* 得到一个结点 */
static NodeType *GetNode(const int, const int);
/* 测试链表是否为空, 空为TRUE,非空为FALSE */
static unsigned EmptyList(const NodeType *);

int main(void)
{ int n, m;
NodeType *pHead=NULL;
while(1)
{printf("please input the number of the person n(<=%d):",MAX_NODE_NUM);
scanf("%d",&n);
printf("and Initial password m:");
scanf("%d",&m);
if(n>MAX_NODE_NUM)
{printf("The number is too big, please input again!\n");
continue;
}
else
break;
}
CreaList(&pHead,n);
printf("\n------------Circulation chain table primitive printing-------------\n");
PrntList(pHead);
printf("\n--------------the situation of Sets out printing---------------\n");
StatGame(&pHead, m);
printf("\n\"Joseph link\"The question completes!\n");
return 0;
}
static void CreaList(NodeType **ppHead, const int n)
{
int i,iCipher;
NodeType *pNew, *pCur;

for(i=1;i<=n;i++)
{
printf("input the %d person's password:",i);
scanf("%d", &iCipher);
pNew=GetNode(i,iCipher);
if(*ppHead==NULL)
{
*ppHead=pCur=pNew;
pCur->next=*ppHead;
}
else
{
pNew->next=pCur->next;
pCur->next=pNew;
pCur=pNew;
}
}
printf("Completes the e-way circulation chain table the foundation!\n");
}

static void StatGame(NodeType **ppHead, int iCipher)
{
int iCounter, iFlag=1;
NodeType *pPrv, *pCur, *pDel;

pPrv=pCur=*ppHead;
/* 将pPrv初始为指向尾结点,为删除作好准备 */
while(pPrv->next!=*ppHead)
pPrv=pPrv->next;

while(iFlag) /* 开始搞了! */
{
/* 这里是记数,无非是移动iCipher-1趟指针! */
for(iCounter=1;iCounter<iCipher;iCounter++)
{
pPrv=pCur;
pCur=pCur->next;
}
if(pPrv==pCur) /* 是否为最后一个结点了 */
iFlag=0;
pDel=pCur; /* 删除pCur指向的结点,即有人出列 */
pPrv->next=pCur->next;
pCur=pCur->next;
iCipher=pDel->cipher;
printf("The %d person Leaving ranks, password: %d\n",
pDel->id, /* 这个编号标识出列的顺序 */
pDel->cipher);
free(pDel);
}
*ppHead=NULL; /* 没人了!为了安全就给个空值 */
}

static void PrntList(const NodeType *pHead)
{
const NodeType *pCur=pHead;

if (EmptyList(pHead))
return;

do
{
printf("The %d person, password: %d\n",pCur->id,pCur->cipher);
pCur=pCur->next;
} while (pCur!=pHead);
}

static NodeType *GetNode(const int iId,const int iCipher)
{
NodeType *pNew;

pNew=(NodeType *)malloc(sizeof(NodeType));
if(!pNew)
{
printf("Error,the memory is not enough!\n");
exit(-1);
}
pNew->id=iId;
pNew->cipher=iCipher;
pNew->next=NULL;

return pNew;
}

static unsigned EmptyList(const NodeType *pHead)
{
if(!pHead)
{
printf("The list is empty!\n");
return TRUE;
}

return FALSE;
}
laolaoliu2002 2008-03-24
  • 打赏
  • 举报
回复
约瑟夫算法:n个人围成一圈,每人有一个各不相同的编号,选择一个人作为起点,然后顺时针从1到k数数,每数到k的人退出圈子,圈子缩小,然后从下一个人继续从1到k数数,重复上面过程。求最后推出圈子的那个人原来的编号。

思路:按照上面的算法让人退出圈子,直到有n-1个人推出圈子,然后得到最后一个退出圈子的人的编号。

程序:坐成一圈的人的编号不需要按序排列

#define N 100
int yuesefu1(int data[],int sum,int k)
{
int i=0,j=0,count=0;
while(count<sum-1)
{
if(data[i]!=0)/*当前人在圈子里*/
j++;
if(j==k)/*若该人应该退出圈子*/
{
data[i]=0;/*0表示不在圈子里*/
count++;/*退出的人数加1*/
j=0;/*重新数数*/
}
i++;/*判断下一个人*/
if(i==sum)/*围成一圈*/
i=0;
}
for(i=0;i<sum;i++)
if(data[i]!=0)
return data[i];/*返回最后一个人的编号*/
}

void main()
{
int data[N];
int i,j,total,k;
printf("\nPlease input the number of every people.\n");
for(i=0;i<N;)/*为圈子里的人安排编号*/
{
int input;
scanf("%d",&input);
if(input==0)
break;/*0表示输入结束*/
for(j=0;j<i;j++)/*检查编号是否有重复*/
if(data[j]==input)
break;
if(j>=i&&input>0)/*无重复,记录编号,继续输入*/
{
data[i]=input;
i++;
}
else
printf("\nData error.Re-input:");
}
total=i;
printf("\nYou have input:\n");
for(i=0;i<total;i++)
{
if(i%10==0)
printf("\n");
printf("%4d",data[i]);
}
printf("\nPlease input a number to count:");
scanf("%d",&k);
printf("\nThe last one's number is %d",yuesefu1(data,total,k));
}
不想低调 2008-03-24
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <malloc.h>
#define NULL 0
#define LEN sizeof(struct student)
struct student
{
int num;
struct student *next;
};
struct student *creat(void)
{
struct student *head ,*p1,*p2;
int n,i;
p1=p2=(struct student *)malloc(LEN);
i=1;n=0;
p1->num=i;
head=NULL;
while(p1->num <=50)
{
n++;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct student *)malloc(LEN);
p1->num=++i;
}
p2->next=head; //
return(head);
}

struct student *del(struct student *head,int num)
{
struct student *p1,*p2;
int i,n=num;

do
{
if(n==num)p1=head;
else p1=p1->next;

for(i=0;i <=1;i++)//跳2个
{
p2=p1;
p1=p1->next;
}
p2->next=p1->next;
n--;
}
while(n>1);
return(p1);
}
int main()
{
int i=0;
struct student *p, *head;
p=creat();
head=p;
if(p!=NULL)
do
{ if((++i)%10==0)
printf("\n");
printf("%d ",p->num);
p=p->next;
}
while(p!=head); //条件错误

printf("\n最后剩下的数字是:%d",del(head,50)->num);
getchar();
}

稍微做点修改..
嵌入式农民 2008-03-24
  • 打赏
  • 举报
回复
看错了,这个程序以前做过,不过数据是存在数组中,没这么麻烦
嵌入式农民 2008-03-24
  • 打赏
  • 举报
回复
你的结果是不是总是1,因为你DEL函数中的循环设计并没有实现这个算法,因为每次都从第一个人开始数,所以得不到正确的结果,你看是不是?

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧