求解JOSEPHUS问题

《数据结构》实验报告

                    题目:求解JOSEPHUS问题


1、程序功能:

解决约瑟夫问题。约瑟夫问题可描述如下:设有n个人围成一个环,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人开始数,数到第m的人又出列,如此重复,直至所有人都出列为止。求这些人出列的顺序。

2、数据结构描述:

向量法数据结构。定义了一个数组,每个元素代表一个人,元素的数值代表人的序号。当数到最后一个元素时,转到第一个元素继续数,以此模拟一个环。

循环链表法数据结构。定义了一个循环链表,每个结点包括一个序号和一个指针。每个结点代表一个人,序号代表人的序号。头指针指示第一个结点,即第一个人。

3、程序结构描述:

1)         构造一个数组或循环链表,并输出。

2)         查找起始元素,并顺延m。找到需要被删除的元素,并输出。

3)         删除需要被删除的元素,并将后面的元素提前一位。

4、算法描述:

向量法。构造好数组后,找到第s个元素,即A[s-1]。然后循环,每次s+1,直至顺延到第s+m-1个元素A[s+m-2],即需要被删除的数。若s+m-1超出数组长度,则在数到最后一个元素时需从第一个元素继续数,以此类推,直到s+m-1小于或等于数组长度。令s+m-2=d,此时,所要被删除的数为A[d]。输出A[d]。然后将A[d]后面的元素都提前一位,用A[d+1]覆盖A[d]来删除A[d]

循环链表法。构造好循环链表后,找到第s个结点,即结点数据为s的结点。令指针p指向第s个结点,然后循环,每次p=p—>next,直到顺延m次后,p指向所需被删除的结点。然后将此结点删除,并使p=p—>next。以此类推,直到只剩下一个结点,输出此结点。

5、程序测试方案与测试结果

向量法。最大人数为100。依次输入n(人数)回车s(起始数)回车m(顺延数)回车。

结果:输出从1n的数组后显示出列的顺序。


循环链表法。依次输入n(人数)回车s(起始数)回车m(顺延数)回车。

结果:输出从1n的链表结点数据后显示出列的顺序。


附录:设计文档与程序源代码;

向量法à

#include <stdio.h>

void main()

{

int n,m,s,d,i,j,l,a[100],dq(int d,int l);

scanf("%d%d%d",&n,&s,&m);

for(i=0;i<n;i++)

{a[i]=i+1;

printf("%d         ",a[i]);}

printf("/n");

l=n;

while(l)

{

if(s+m-1<=l)

d=s+m-2;

else

d=s+m-l-2;

d=dq(d,l);

printf("%d         ",a[d]);

for(j=d;j<=l-2;j++)

a[j]=a[j+1];

if(d+1!=l)

s=d+1;

else

s=1;

l--;

}

}

 

int dq(int d,int l)

{

if(d+1>l)

{d--;

d=dq(d,l);}

else

return(d);

}

 

 

循环链表法à

#include <stdio.h>

#include <malloc.h>

#define NULL 0

#define LEN sizeof(struct yue)

struct yue

{

int num;

struct yue * next;

};

int n;

struct yue *head;

struct yue * creat(void)

{

int i;

struct yue * head;

struct yue * p1,* p2;

p1=p2=(struct yue *)malloc(LEN);

scanf("%d",&n);

p1->num=1;

head=NULL;

for(i=0;i<n;)

{

i=i+1;

if(i==1) head=p1;

else p2->next=p1;

p2=p1;

p1=(struct yue *)malloc(LEN);

p1->num=i+1;

}

p2->next=head;

return(head);

}

void output(struct yue *p,int n)

{

int i=1;

while(i<=n)

{

printf("%d         ",p->num);

p=p->next;

i++;

}

 

printf("/n");

}

void del(struct yue *head,int s,int m)

{

int u;

struct yue * p3,* p4;

p3=head;

while(s!=p3->num)

{

p3=p3->next;

}

while(p3->next!=p3)

{

u=1;

while(u<m)

{

p4=p3;

p3=p3->next;

u++;

}

printf("%d         ",p3->num);

p4->next=p3->next;

p3=p3->next;

}

printf("%d         ",p3->num);

}

void main()

{

int s,m;

struct yue *head1;

head1=creat();

scanf("%d%d",&s,&m);

output(head1,n);

del(head1,s,m);

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值