实习3:约瑟夫问题
约瑟夫问题实验报告

X X X X X X X X实验报告课程:数据结构班级:姓名:学号:成绩:指导教师:实验日期:2012.3实验密级:预习程度:实验时间:仪器组次:必修/选修:必修实验序号:01实验名称:线性结构的应用——约瑟夫问题实验目的与要求:编程实现约瑟夫问题。
假设有n个人围圈而坐,现在从第k人开始数数,数到m的人出列,紧接着的后续人又从1开始数数,到m出列,如此重复下去,直到全体人员出列。
编程实现新出列的数字序号输出。
实验仪器:名称型号数量微机1一、概要设计本程序使用了循环链表这一数据结构。
循环链表在普通链表的基础上,将最后一个节点的指针域指向头结点。
具体定义为:typedef struct CLNode{ int data;struct CLNode *next;}Node;//定义单向循环链表结构体,并令最后一个指针指向头结点流程图如下:注:在*处调用子函数为head 分配存储空间,如果内存不够,结束程序 head=head->next; head->data=i; i++; head==NULL? i<=n? 为p 分配存储空间,如果内存不够,结束程序 pr->next=p;p->data=i; p->next=head; pr=p; 开始 从主函数中接受头结点指针head ,n i=1,Node *p=NULL , Node *pr=head; 返回head 是是否 否图2——子函数:建立n 阶循环链表,返回链表的头指针图1——主函数开始 输入总人数(n)、从第几个人开始数(k)、数到第几个人出列(m) 构造n 项循环链表*执行”head=head->next ”k 次,修改头指针指向Node *head=NULL;int i=0; 按顺序输出? 否 是是否 结束释放链表剩余存储空间 输出head->data 实现报数并出列* head!=head->ne xt?直接按顺序输出开始从主函数中接受head和mint i=1;Node *p=head;Node *pre=NULL;执行:”pre=p;p=p->next;”m次,模拟报数并移动指针此时,p->data便是出列编号,输出其值删除p指向的节点,令p之后的节点为head返回head图3——子函数:当链表中的结点个数大于1,调用此函数,实现目标出列,并删除该节点,另该节点下一结点为头结点,返回修改后的头结点二、详细设计本程序核心算法主要有两部分:一是建立循环链表,二是实现目标人员的出列。
“约瑟夫”问题及若干变种

“约瑟夫”问题及若⼲变种“约瑟夫”问题及若⼲变种例1、约瑟夫问题(Josephus)[问题描述]M只猴⼦要选⼤王,选举办法如下:所有猴⼦按1…M编号围坐⼀圈,从第1号开始按顺序1,2,…,N报数,凡报到N的猴⼦退出到圈外,再从下⼀个猴⼦开始继续1~ N报数,如此循环,直到圈内只剩下⼀只猴⼦时,这只猴⼦就是⼤王。
M和N由键盘输⼊,1≤N,M≤10000,打印出最后剩下的那只猴⼦的编号。
例如,输⼊8 3,输出:7。
[问题分析1]这个例题是由古罗马著名史学家Josephus提出的问题演变⽽来的,所以通常称为Josephus(约瑟夫)问题。
在确定程序设计⽅法之前⾸先来考虑如何组织数据,由于要记录m只猴⼦的状态,可利⽤含m个元素的数组monkey来实现。
利⽤元素下标代表猴⼦的编号,元素的值表⽰猴⼦的状态,⽤monkey[k]=1表⽰第k只猴⼦仍在圈中,monkey[k]=0则表⽰第k只猴⼦已经出圈。
程序采⽤模拟选举过程的⽅法,设变量count表⽰计数器,开始报数前将count置为0,设变量current表⽰当前报数的猴⼦编号,初始时也置为0,设变量out记录出圈猴⼦数,初始时也置为0。
每次报数都把monkey[current]的值加到count上,这样做的好处是直接避开了已出圈的猴⼦(因为它们对应的monkey[current]值为0),当count=n时,就对当前报数的猴⼦作出圈处理,即:monkey[current]:=0,count:=0,out:=out+1。
然后继续往下报数,直到圈中只剩⼀只猴⼦为⽌(即out=m-1)。
参考程序如下:program josephus1a {模拟法,⽤数组下标表⽰猴⼦的编号}const maxm=10000;var m,n,count,current,out,i:integer;monkey:array [1..maxm] of integer;beginwrite('Input m,n:');readln(m,n);for i:=1 to m do monkey[i]:=1;out:=0; count:=0; current:=0;while out<m-1 dobeginwhile count<n dobeginif current<m then current:=current+1 else current:=1;count:=count+monkey[current];end;monkey[current]:=0; out:=out+1; count:=0end;for i:=1 to m doif monkey[i]=1 then writeln('The monkey king is no.',i);readlnend.[运⾏结果]下划线表⽰输⼊Input m,n:8 3The monkey king is no.7 {时间:0秒}Input m,n:10000 1987The monkey king is no.8544 {时间:3秒}[反思] 时间复杂度很⼤O(M*N),对于极限数据会超时。
实验报告 约瑟夫问题

pCur->next = pNew;
pCur = pNew;
printf("结点%d,密码%d\n",pCur->id, pCur->cipher);
}
}
printf("完成单向循环链表的创建!\n");
}
(3)运行"约瑟夫环"问题
static void StartJoseph(NodeType **, int)
exit(-1);
}
pNew->id = iId;
pNew->cipher = iCipher;
pNew->next = NULL;
return pNew;
}
(6)测试链表是否为空,空为TRUE,非空为FALSE
static unsigned EmptyList(const NodeType *pHead)
实验内容
利用循环链表实现约瑟夫环求解。
实验说明
1.问题描述
约瑟夫问题的:编号为1,2,....,N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的M值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。
{
if(!pHead)
{
return TRUE;
}
return FALSE;
}
实验中遇到的问题及解决方法
实验结果如下:
实验总结(结果和心得体会)
第三周约瑟夫问题

实验3(第3周实验指导)约瑟夫序列一、实验题目求解《约瑟夫序列》的问题二、实验课时2课时。
三、实验目的1.掌握“管理信息系统”书本第3章的相关内容2.学习“单向链表”的数据结构及其有关操作3.学习编写程序四、实验内容1.学习约瑟夫序列2.学习《约瑟夫序列》程序的例子(本例从一号开始报数)3.作业:编写程序求解以下问题,现有运动会门票要赠与你们班(两个班各有67人,学号从1到67)的10个幸运儿,要求采用约瑟夫序列来抽签,全班以学号顺序排号围坐在一张圆桌周围。
从编号为18的人开始顺序报数,数到18的那个人出列;他的下一个人又从1开始报数,数到18的那个人又出列;依此规律重复下去,直到圆桌周围的剩下10个人就是幸运儿。
程序有如下要求:a)读取你们班名单文本文件的内容,存入一个单向链表,并以学号排序,节点要求保存学号,姓名和性别等信息。
b)针对这个链表进行以上的问题求解。
c)程序输出10个幸运儿的学号,姓名,性别五、实验报告要求1.独立完成,作业交电子版2.给出程序源代码。
3.写出10个幸运儿的名字4.写实验心得或小结。
程序代码:#include <stdio.h>#include <stdlib.h>typedef struct node{int number;char info[100]; //将学生的学号,姓名,性别等信息都利用info[]来存储struct node *next;}dlnode,*dlink;struct node *head,*p,*temp1,*temp2;FILE *fp;struct node* Creatlist(int num) //创建班级列表{int i;head=(dlnode*)malloc(sizeof(dlnode));head->number=1;head->next=head;p=head;if((fp=fopen("E:\\Program Files\\class1.txt","rb"))==NULL) //打开存储学生信息的文本class2.txt{printf("\nCannot open file strike any key exit!");exit(1);}fgets(head->info,100,fp); //头结点可用于存储标题信息for(i=1;i<=num;i++){temp1=(dlnode*)malloc(sizeof(dlnode));temp1->number=i;fgets(temp1->info,100,fp); //将每个学生的信息导入入相应的info字符数组中,//每个学生对应一条info[]信息temp1->next=p->next;p->next=temp1;p=temp1;}p=head;printf("班级名单如下:\n");printf("序号学号姓名性别\n\n");printf(" %s\n",head->info);while(p->next!=head){printf(" %s\n",p->next->info);p=p->next;}return head;}void drowlots(dlnode *head,int num,int m) //主处理函数{int i,j;p=head;i=1;j=num;while(j!=10){if(i==m&&p->next!=head){temp2=p->next;printf(" %d \n",temp2->number); //可输出被淘汰的学生的序号p->next=temp2->next;free(temp2);i=1;j=j-1;}else{if(p->next==head) i--;p=p->next;i++;}}p=head->next;printf("\n10名幸运儿如下:\n\n");printf("序号学号姓名性别\n\n");printf(" %s\n",head->info);while(p!=head){printf(" %s\n",p->info);p=p->next;}}void main() //主函数{int n,m;n=67;head=Creatlist(n);printf("输入报数的编号:");scanf("%d",&m);drowlots(head,n,m);system("pause");}3.实验心得在本实验中,存在的难点是就是如何导入文件已经如何建立链表,特别是在导入文件的过程中我也遇到了门槛,就是在写导入路径时,WIN7系统只识别英文,汉字和数字是无法识别,比如文档一班.txt在路径D的文件programfiles下是无法读入的,所以应该把文档名一班.txt 更改为class1.txt才能被识别!。
兰州大学数据结构实验 约瑟夫问题实验报告(数组)

兰州大学信息科学与工程学院数据结构实验报告课程名称数据结构实验名称数据结构试验专业班级姓名学号实验日期第 11 周星期日节实验地点贺兰堂2012—2013学年度第一学期一、实验目的1、用数组来实现约瑟夫问题二、实验内容1、试分别用线性表的向量存储结构和数组存储结构来实现约瑟夫(Josephu)问题。
约瑟夫问题如下:设有n个人围坐圆桌周围。
从某个位置上的人开始从1报数,数到m的人便出列,下一个人(第m+1个)又从1报数开始,数到m的人便是第2个出列的人,依次类推,直到最后一个人出列为止,这样就可以得到一个人员排列的新次序。
例如,n=8,m=4,从第1个人数起,得到的新次序为48521376.三、实验环境1、硬件配置:Pentium(R) Dual-Core9 CUP E6500 @2.93GHz,1.96的内存2、软件环境:Microsoft Windows XP Professional Service Pack 3,Microsoft Visual C++ 6.0四、需求分析1、输入的形式和输入值的范围:根据题目要求与提示输入数据的总数,间隔数和开始计数的位置2、输出的形式:输出每个挑选的数据3、程序所能达到的功能:从开始计数的位置起,每隔间隔数,就把该位置的数字输出,同时此数被释放掉,然后从继续此操作,若到数据结束位置,则重新开始进行。
程序结束的条件是所有的数据输出,释放掉。
4、测试数据:输入一个链表,首先输入数据总数,然后输入间隔数,再输入起始位置,若起始位置大于数据总数,会提示错误,要求重新输入起始位置,直至起始位置不大于总数。
然后开始输入数据,数据以空格隔开,最后输出结构。
如:输入数据总数8,间隔数4,起始位置1,输入数据 1 2 3 4 5 6 7 8输出的链表为:4 8 5 2 1 3 7 6五、概要设计为了实现上述操作,应以数组结构。
1、本程序包含二个模块:(1)主程序模块;3、流程图输入数据的总数num间隔数count起始位置start当Start>num输入总数num输入起始位置start当I<num按输入顺序将输入的数字存进a数组中设定这个循环是死循环I++I==num是否I=i%numA[i]!=0是否I++J==count是否B[k++]=a[i]A[i]=0J=0K==num是否跳出循环当K<num输出数组B六、详细设计主函数详解#include"stdio.h"void main(){int a[10],b[10],i,j,k,count,num,start;printf("请输入总数:");scanf("%d",&num);printf("请输入间隔数:");scanf("%d",&count);printf("请输入起始位置:");scanf("%d",&start);printf("\n");while(start>num){printf("请重新输入:\n");printf("请输入总数:");scanf("%d",&num);printf("请输入起始位置:");scanf("%d",&start);}printf("请输入数据:\n");for (i=0;i<num;i++)scanf("%d",&a[i]);printf("\n");i=start-1;//为了保持起始条件匹配k=0;for(j=1;;)//为死循环{i++;if (i==num)//为了实现每次i的循环遍历A数组i=i%num;if (a[i]!=0)//只有a[i]不为零时,才能j++j++;if (j==count)//达到间隔数{b[k++]=a[i];//将a数组的值赋给b数组a[i]=0;j=0;//使记录间隔的重新开始计数}if (k==num)//当b数组有了a数据全部数据时,结束循环break;}printf("标准顺序为:\n");for(k=0;k<num;k++)printf(" %d",b[k]);printf("\n");}3、完整的程序:#include"stdio.h"void main(){int a[10],b[10],i,j,k,count,num,start;printf("请输入总数:");scanf("%d",&num);printf("请输入间隔数:");scanf("%d",&count);printf("请输入起始位置:");scanf("%d",&start);printf("\n");while(start>num){printf("请重新输入:\n");printf("请输入总数:");scanf("%d",&num);printf("请输入起始位置:");scanf("%d",&start);}printf("请输入数据:\n");for (i=0;i<num;i++)scanf("%d",&a[i]);printf("\n");i=start-1;k=0;for(j=1;;){i++;if (i==num)i=i%num;if (a[i]!=0)j++;if (j==count){b[k++]=a[i];a[i]=0;j=0;}if (k==num)break;}printf("标准顺序为:\n");for(k=0;k<num;k++)printf(" %d",b[k]);printf("\n");}七、程序使用说明及测试结果1、程序使用说明(1)本程序的运行环境为VC6.0。
约瑟夫问题的链式求解法

实验一约瑟夫问题求解一、实验目的1、掌握上机调试线性表的基本方法;2、掌握线性表的基本操作:插入、删除、查找等运算在顺序存储结构和链式存储结构上的运算。
3、掌握约瑟夫问题求解算法二、实验内容1、认真阅读和掌握本实验的参考程序,并上机运行本程序,可尝试完善删除、查找等运算。
2、参考第二章课件中对瑟夫问题求解算法的描述,选择一种存储结构实现该问题的求解。
三、注意事项:1、在磁盘上创建一个目录,专门用于存储数据结构实验的程序,可通过U盘或邮箱长期保存程序。
2、实验报告要求:(1)算法的完整代码;(2)程序运行结果及分析;(3)实验总结。
四、参考程序1、顺序表的插入(1)程序代码#include "stdio.h"#include "stdlib.h"typedef struct SeqList{int data[100];int length; /* 表长*/}SeqList , *PSeqList;PSeqList creaeNullList_seq()/* 创建空线性表*/{PSeqList palist=(PSeqList)malloc(sizeof(struct SeqList));if(palist!=NULL){palist->length=0;return(palist);}printf("Out of space!!\n");return NULL;}int isNullList_seq(PSeqList palist)/* 判断是否空线性表*/{return (palist->length==0);}int insertPre_seq(PSeqList palist,int p,int x){int q;if(palist->length>=100){printf("overflow!\n");return(0);}if(p<0 || p>palist->length){printf("Not exist!\n");return(0);}if(isNullList_seq(palist)){palist->data[0]=x;palist->length=1;return(1);}for(q=palist->length-1;q>=p;q--)palist->data[q+1]=palist->data[q] ;palist->data[p]=x;palist->length= palist->length+1;return(1);}void main(){int i;PSeqList list;list=creaeNullList_seq(); /* 创建空线性表*/printf("插入前的顺序表为:\n ");for(i=0;i<=9;i++){insertPre_seq(list,i,i*i);printf(" %d " , list->data[i]);}insertPre_seq(list,5,55);/*在下标为5的元素之前插入元素55*/ printf("\n\n插入后的顺序表为:\n ");for(i=0;i<list->length;i++)printf(" %d " , list->data[i]);printf("\n\n");}(2)运行结果2、约瑟夫问题顺序表的实现int josephus_ SeqList (PSeqList josephus_seq, int s, int m){ /*求解约瑟夫问题的出列元素序列入口参数:已经存放数据的顺序表,起始位置s,数m , 出口参数:1表示成功,0表示表中没有元素*/int s1,i,w;if ( ! josephus_seq->length){ printf(“表中无元素”);return (0); }s1=s - 1; /*data数组中下标从0开始*/printf(“输出约瑟夫序列:”);for( i= josephus_seq->length; i>0; i --;){ s1=(s1+m-1)% i; /*找到出列元素的下标*/w= josephus_seq->data[s1];printf(“%d\t”, w)Delete_SeqList(josephus_seq,s1); /*删除出列元素*/} /*for */return(1); /*成功返回*/}3、约瑟夫问题链表的实现int josephus_ LinkList (LinkList josephus_Link, int s, int m){ /*求约瑟夫问题的出列元素序列,入口参数:已经存放数据的链表头指针的地址,起始位置s,数m ,出口参数:1表示成功,0表示表中没有元素*/LinkList p,pre; /*p指向当前结点,pre指向其前驱结点*/int count;if ( ! josephus_Link){ printf(“表中无元素”);return (0);}/*找第s个元素*/p= josephus_Link;for(count=1;count<s;count++) /*查找第s个结点,用p作为第s个结点的指针*/p=p->next;printf(“输出约瑟夫序列:”);while ( p!=p->next) /*输出n-1个元素个结点*/{ for(count=1;count<m;count++){ pre=p;p=p->next;} /*for*/printf(“%d\t”, p->data);pre->next=p->next;free(p);p=pre->next;}/*while*/printf(“%d\t”,p->data); /*输出最后一个元素个结点*/free(p);return 1;}2.约瑟夫问题的求解(1)程序代码#include"stdio.h"#include"stdlib.h"typedef struct node{int data;struct node *next;}lnode,*linklist;linklist Init_josephus(void){linklist head;head=(linklist)malloc(sizeof(lnode));if(!head){printf("Apply place is faliure!\n\n");return NULL;}head->next=NULL;return head;}void Create_josephus(linklist JOS){linklist p,q,H;int x;p=H=JOS;printf("please enter elements:\n");scanf("%d",&x);p->data=x;scanf("%d",&x);while(x!=-1){q=(linklist)malloc(sizeof(lnode));q->data=x;q->next=p->next;p->next=q;p=q;scanf("%d",&x);}p->next=H;p=H;printf("\n");while(p->next!=H){printf("%3d",p->data);p=p->next;}printf("%3d",p->data);printf("\n");}int josephus_linklist(linklist josephus_link,int s,int m){linklist p,pre;int count;if(!josephus_link){printf("There are not have elements in the list!\n");return 0;}p=josephus_link;for(count=1;count<s;count++)p=p->next;printf("The list of josephus is :\n");while(p!=p->next){for(count=1;count<m;count++){pre=p;p=p->next;}printf("%d\t",p->data);pre->next=p->next;free(p);p=pre->next;}printf("%d\t",p->data);free(p);printf("\n");return 1;}main(){int i,j;lnode *Josephus;Josephus=Init_josephus();Create_josephus(Josephus);printf("please enter the first elements number and steps:\n");scanf("%d%d",&i,&j);josephus_linklist(Josephus,i,j);return 2;}(2)程序运行结果(3)实验总结这次实验用的是链式存储结构来解决约瑟夫问题,第一遍编写的程序中,指针使用的有点混乱,头结点不知该如何处理,指针问题解决后,在运行的过程中,头结点的问题一直解决不了即创建的表有问题还没有解决,表的创建中数据的输出里一个很大的数,原因就是头结点中的值域为空;后来将两个结构体类型的指针同时指向头指针,才将问题顺利解决。
约瑟夫问题的经典三个例子

约瑟夫问题的经典三个例子以下是 9 条关于约瑟夫问题的经典例子:例子 1:想想看,一群小朋友围成一圈玩游戏,就像我们小时候那样。
这时候说从某个小朋友开始报数,每隔一个人淘汰,最后剩下的那个就是胜利者。
这不就是约瑟夫问题嘛。
就好像在一个神秘的游戏圈子里,大家都紧张又兴奋地等待着命运的裁决。
例子 2:你能想象军队里士兵们站成一圈,然后用这种方式来决定谁去执行特殊任务吗?哎呀呀,那场面肯定很刺激。
每个士兵心里都七上八下的,不知道自己是不是那个“幸运儿”,这和约瑟夫问题如出一辙。
例子 3:假如在一场盛大的聚会中,大家玩这样的游戏,是不是超级有趣?就像一个魔法圈,把大家的注意力都吸引过来了。
每淘汰一个人,大家就会一阵惊呼,这不正是约瑟夫问题带来的独特体验嘛。
例子 4:你看过那种生存挑战节目吗?选手们围成一圈,然后通过类似约瑟夫问题的规则来淘汰人。
哇塞,那紧张的氛围,可不就是在经历一场残酷的竞争,这就是约瑟夫问题在现实中的精彩呈现呀!例子5:好比一群探险家在荒岛上,为了分配重要资源而采取这种方式。
每个人都祈祷自己不要被先淘汰掉,这种感觉是不是很奇妙?这就是约瑟夫问题带来的不确定性啊。
例子6:想象一下公司团建的时候玩这个,大家既期待又担心。
“哎呀,可别先轮到我呀!”“哇,我居然留下来了。
”这种种反应,不就是约瑟夫问题的魅力所在吗?例子 7:学校运动会上,各班学生围成一圈进行比赛,多刺激呀!有人欢喜有人忧,这不就是约瑟夫问题所引发的情绪波澜吗?例子 8:在一个神秘的魔法学院里,学生们也用这种方式来选拔优秀学员。
每一个人都全神贯注,这和约瑟夫问题一样充满了悬念呢!例子9:如果在一个古老的部落中,用约瑟夫问题来决定首领的继承人,那该是多么惊心动魄的场面啊。
大家的心都提到了嗓子眼,。
约瑟夫问题

约瑟夫问题一、问题描述和要求1、问题描述约瑟夫问题是这样的:设有n个人围圆桌坐成一圈,现从第s个人开始报数,数到m的人出列,接着从出列的下一个人开始重新报数,数到m的人又出列,如此重复下去,直到所有人都出列为止。
2、程序设计要求(1)、通过本学期《数据结构》的学习,综合运用已学过的理论和技能去分析和解决约瑟夫问题,加深对数据结构课程理论的理解和运用、切实加强自己的实践动手能力和创新能力。
(2)、结合C语言程序设计、数据结构中所学的理论知识,小组独立设计方案,培养分析与解决问题的能力。
(3)、学会查阅相关手册和资料,进一步熟悉常用算法的用途和技巧,掌握这些算法的具体含义。
(4)、认真调试程序,学会改正程序中的错误,尝试不同的方法实现同一功能,培养严谨的作风和科学的态度。
二、个人所负责的工作1、算法思路约瑟夫问题的解决可以用线性链表,循环链表,数组等多种方法,我们采用线性链表解决该问题,采用分块的设计思路,利用函数调用解决问题。
本算法采用for循环解决线性链表的建立,用printf函数输出链表,利用for循环找到第s个人开始报数,再利用一个for循环找到第m个人,然后多重if语句讨论不同情况的处理,最后通过函数调用解决约瑟夫问题。
2、我负责的工作在这次程序设计中,我主要负责对整个题目设计思路进行分析和对程序的注释。
我们刚设计出来的程序存在着种种问题,各部分程序都需要进行一定的修改和完善,比如线性链表不能够正常输入,主函数对用户的输入要求的描述太过笼统,输出函数不能调用等等。
我就是不断发现这些问题并完善它们,使程序能够正确的运行。
然后我和其他组员经过商议,对程序的各部分含义进行注释。
在程序演示时我主要负责对整个题目设计思路分析及组员介绍。
以下是我修改过的程序之一:NODE *creatlinklist(int n)/*建立线性链表*/{ int i;NODE *head,*p,*q;/*定义整形实参i,指针head、p、q*/if(n==0)return(NULL);/*如果n=0建立一个空链表*/elsehead=(NODE *)malloc(sizeof *head);/*申请一个结点为表头*/q=head;for (i=1;i<=n;i++)/*将n个结点输入到单链表中*/{p=(NODE *)malloc(sizeof *head);printf("输入数据:");p->info=getche();/*getche功能: 输入后立即从控制台取字符,不以回车为结束*/printf("\n");q->next=p;/*q指向表尾,准备导入下一个结点*/q=p;}p->next=NULL;/*将最后一个结点的链域置为空*/return(head);}三、结论经过这次程序设计任务,我认真的复习了数据结构中学习过的理论知识,尤其是对线性链表这一部分进行了认真的归纳总结,对数据结构的认识更深刻了,对线性链表的建立、插入、删除、查找等操作的运用更加熟练,对for循环、输入输出函数等更加了解,而且我意识到今后我可以利用这些函数解决更多的实际问题。
约瑟夫问题(报数问题)

约瑟夫问题(报数问题)约瑟夫问题(报数问题)起因:据说著名犹太历史学家Josephus有过以下的故事:在罗⻢⼈占领乔塔帕特后,39个犹太⼈与Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被敌⼈抓到,于是决定了⼀个⾃杀⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀,然后再由下⼀个重新报数,直到所有⼈都⾃杀⾝亡为⽌。
然⽽Josephus 和他的朋友并不想遵从。
⾸先从⼀个⼈开始,越过k-2个⼈(因为第⼀个⼈已经被越过),并杀掉第k个⼈。
接着,再越过k-1个⼈,并杀掉第k个⼈。
这个过程沿着圆圈⼀直进⾏,直到最终只剩下⼀个⼈留下,这个⼈就可以继续活着。
问题是,给定了和,⼀开始要站在什么地⽅才能避免被处决。
Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在第16个与第31个位置,于是逃过了这场死亡游戏。
中,类似问题⼜称为约瑟夫环,⼜约瑟夫问题,是⼀个和中的问题,在计算机的中,类似问题⼜称为约瑟夫环,⼜约瑟夫问题,是⼀个和中的问题,在计算机的称“丢⼿绢问题”。
及过程就是先决定⼀个判断数字为k,若第⼀个⼈从⼀开始报数,若报数到k,则第k个⼈就要出来,从第k+1个⼈,⼜重新开始从⼀开始报数,报的K的⼈再次出队,若所有⼈都报过⼀遍,则从第⼀个⼈开始循环,依次类推。
直到只剩下⼀个⼈为⽌。
解题步骤:可以将约瑟夫问题看成⼩朋友循环排队的⽅法。
⼩朋友们排成⼀队,每⼀位⼩朋友报数结束后,如果报的数不是出队的数(判断数字k),则⾃动到对尾排队,如果等于出队数,这个⼩朋友出队。
⼀直循环,直到剩下⼀个⼩朋友为⽌//这是判断数字为3的时候,其他的类似//item=int(input())a=[]num1=0num2=3for i in range(1,item+1):a.append(i)while len(a)>1:num1+=1t=a.pop(0)if num1!=3:a.append(t)else:num1=0print(a[0])举⼀反三:若不确定让⽤户随意输⼊判断数item,m=map(int,input().split(''))a=[]num1=0num2=3for i in range(1,item+1):a.append(i)while len(a)>1:num1+=1t=a.pop(0)if num1!=m:a.append(t)else:num1=0print(a[0])这⾥使⽤while会更加简单⼀些,⽐⽤for-in循环更好写。
数据结构实验报告—约瑟夫问题求解

数据结构实验报告—约瑟夫问题求解《计算机软件技术基础》实验报告 I —数据结构实验一、约瑟夫斯问题求解一、问题描述1.实验题目:编号 1,2,....,n的n个人顺时针围坐一圈,每人持有一个密码(正整数)。
开始选择一个正整数作为报数上限m,从第一个人开始顺时针自1 报数,报到m的人出列,将他的密码作为新的m值,从他在顺时针方向下一个人开始重新从 1 报数,直至所有人全部出列。
2. 基本要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。
3. 测试数据: n=7,7 个人的密码依次为:3,1,7,2,4,8,4.m初值为6(正确的出列顺序应为 6,1,4,77,2,3)。
二、需求分析1. 本程序所能达到的基本可能:该程序基于循环链表来解决约瑟夫问题。
用循环链表来模拟n 个人围坐一圈,用链表中的每一个结点代表一个人和他所代表的密码。
在输入初始密码后m,对该链表进行遍历,直到第 m个结点,令该结点的密码值作为新的密码值,后删除该结点。
重复上述过程,直至所有的结点被释放空间出列。
2. 输入输出形式及输入值范围:程序运行后提示用户输入总人数。
输入人数n 后,程序显示提示信息,提示用户输入第i个人的密码,在输入达到预定次数后自动跳出该循环。
程序显示提示信息,提示用户输入初始密码,密码须为正整数且不大于总人数。
3.输出形式提示用户输入初始密码,程序执行结束后会输出相应的出列结点的顺序,亦即其编号。
用户输入完毕后,程序自动运行输出运行结果。
4.测试数据要求:测试数据 n=7,7 个人的密码依次为:3, 1, 7, 2, 4, 8,4。
m初值为 6(正确的出列顺序应为6, 1, 4,7, 2, 3, 5)。
三、概要设计为了实现上述功能,应用循环链表来模拟该过程,用结构体来存放其相应的编号和密码信息,因此需要循环链表结构体这个抽象数据类型。
1.循环链表结构体抽象数据类型定义:ADT Node{数据对象:D={ai,bi,ci|ai∈ int,bi ∈ int,ci∈(Node*),i=1,2...,n,n ≥0}:数据关系: R=?基本操作:CreatList(int n)// Order(int m,node *l)}ADT node;构建循环单链表;// 输出函数,输出出列顺序并删除链表中的结点;2.ADT 的 C 语言形式说明:typedef struct Node{int num;//结点的数据域,存放编号;int word; //结点的数据域,存放密码;struct Node *next; //结点的指针域,存放指向下一结点的指针;}Node;Node *CreatList( )// 建立循环单项链表;void Order(Node *h) //输出出列顺序并删除结点;3.主程序流程及其模块调用关系:1) . 主程序流程:先提示用户输入相关数据:总人数,运行循环链表结构体模块,输入每个人持有的密码值,创建出新链表,运行输出函数模块,再输入初始密码m值,输出出列序列。
约瑟夫问题大数据结构实验报告材料

实用标准文档中南民族大学管理学院学生实验报告实验项目: 约瑟夫问题课程名称:数据结构年级:专信息管理与信息系统业指导教师:实验地点:管理学院综合实验室完成日期:小组成员:2012 学年至2013 学年度第丄学期文案大全•、实验目的(1)掌握线性表表示和实现;(2)学会定义抽象数据类型;(3)学会分析问题,设计适当的解决方案;二、实验内容【问题描述】:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
【基本要求】:利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
【测试数据】:m的初值为20 ;密码:3, 1 , 7, 2 , 4, 8, 4 (正确的结果应为 6 , 1 ,4 , 7 , 2, 3,5 )。
三、实验步骤(一)需求分析对于这个程序来说,首先要确定构造链表时所用的插入方法。
当数到m 时一个人就出列,也即删除这个节点,同时建立这个节点的前节点与后节点的联系。
由于是循环计数,所以才采用循环列表这个线性表方式。
程序存储结构利用单循环链表存储结构存储约瑟夫数据(即n个人的编码等),模拟约瑟夫的显示过程,按照出列的顺序显示个人的标号。
编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
基本要求是利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
约瑟夫实验报告

约瑟夫实验报告约瑟夫实验报告约瑟夫实验是一个古老而有趣的数学问题,它源自于古代罗马的历史。
约瑟夫问题的描述是:有n个人围成一个圆圈,从某个人开始,依次报数,每报到第m个人,就将该人从圈中移除,然后从下一个人开始重新报数。
如此循环,直到只剩下最后一个人。
那么,最后剩下的人是谁呢?这个问题看似简单,但实际上却涉及到一些有趣的数学原理。
为了解决这个问题,我们可以通过模拟实验来观察和分析。
在这个实验中,我们选择了一组有限的人数,并设定了一个固定的报数值。
首先,我们选择了一个较小的n值,比如说10。
接下来,我们设定m的值为3。
然后,我们按照约瑟夫问题的规则进行模拟实验。
实验开始时,我们将10个人围成一个圆圈,从第一个人开始报数。
当报到第3个人时,这个人将从圈中移除。
然后,从下一个人开始重新报数。
我们重复这个过程,直到只剩下最后一个人。
通过观察实验结果,我们发现,在这个特定的情况下,最后剩下的人是第4个人。
这个结果似乎有些出人意料,因为我们可能会认为最后剩下的人应该是圈中的某个固定位置。
然而,事实并非如此,最后剩下的人的位置是不确定的,它取决于n和m的值。
为了进一步探究这个问题,我们可以改变n和m的值,观察它们对最后剩下的人的影响。
当n增大时,我们发现最后剩下的人的位置也会随之变化。
而当m的值增大时,最后剩下的人的位置也会发生变化。
这个实验告诉我们,约瑟夫问题并没有一个固定的答案,而是取决于初始条件。
而这种变化的规律则可以通过数学方法进行推导和证明。
通过数学推导,我们可以得出一个结论:对于任意给定的n和m值,最后剩下的人的位置可以用一个数学公式来表示。
这个公式是一个递推公式,它可以通过递归的方式来求解。
通过这个公式,我们可以快速计算出最后剩下的人的位置,而无需进行大量的模拟实验。
约瑟夫实验不仅仅是一个有趣的数学问题,它还有着深刻的数学原理。
通过这个问题,我们可以学习到递推公式的应用,以及如何通过数学方法来解决实际问题。
约瑟夫问题实验报告

约瑟夫问题实验报告(文章一):约瑟夫问题数据结构实验报告中南民族大学管理学院学生实验报告实验项目: 约瑟夫问题课程名称:数据结构年级:专业:信息管理与信息系统指导教师:实验地点:管理学院综合实验室完成日期:小组成员:学年度第(一)、实验目的(1)掌握线性表表示和实现;(2)学会定义抽象数据类型;(3)学会分析问题,设计适当的解决方案;(二)、实验内容【问题描述】:编号为1,2,…,n 的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自 1 开始顺序报数,报到m 时停止报数。
报m 的人出列,将他的密码作为新的m 值,从他在顺时针方向上的下一个人开始重新从1 报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
【基本要求】:利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
【测试数据】:m 的初值为20;密码:3,1,7,2,4,8,4(正确的结果应为6,1,4,7,2,3,5)。
(三)、实验步骤(一)需求分析对于这个程序来说,首先要确定构造链表时所用的方法。
当数到m 时一个人就出列,也即删除这个节点,同时建立这个节点的前节点与后节点的联系。
由于是循环计数,所以才采用循环列表这个线性表方式。
程序存储结构利用单循环链表存储结构存储约瑟夫数据(即n个人的编码等),模拟约瑟夫的显示过程,按照出列的顺序显示个人的标号。
编号为1,2,?,n 的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1 开始顺序报数,报到m 时停止报数。
报m 的人出列,将他的密码作为新的m 值,从他在顺时针方向上的下一个人开始重新从1 报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
基本要求是利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
约瑟夫斯问题实验报告

约瑟夫斯问题实验报告学号150820127 姓名王碧辉一、问题描述1、实验题目约瑟夫斯(Josephus)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数。
报m 的人出列,将他的密码作为新的m值,从他在顺时针方向下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。
试设计一个程序,按出列顺序印出各人编号。
2、基本要求利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
3、测试数据m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4。
m初值为6(正确的出列顺序应为6,1,4,7,2,3,5)。
4、简述每一部分的对象、目的和要求:(1)主函数部分:对象:链表;目的:创建新链表;要求:将该链表初始化。
(2)被调函数部分:对象:结构体;目的:创建循环链表并且模拟约瑟夫斯问题;要求:让链表首尾相接,并且释放原来单链表的头结点空间。
通过该函数的调用,依次输出各结点的编号,并且符合规则。
二、需求分析1.程序所能达到的基本可能:该程序用循环链表来模拟n个人顺时针围坐一圈,用链表中的每一个结点代表一个人,结点结构体中设置两个变量,分别存放其编号以及密码。
在输入初始密码后,对该链表进行遍历,直到遍历到第m个结点,释放其空间,使其出列。
然后用被释放空间结点的密码值作为新的密码值,重复上述过程,直至所有结点被释放空间出列,链表成为空链表。
2.输入输出形式及输入值范围:程序运行后显示提示信息:"Please input a data:",提示用户输入密码信息,在输入达预定次数后自动跳出该循环,同时循环链表创建成功,在主函数中有相应的输出给予检验。
然后程序显示提示信息:"Please input the number m:",提示用户输入初始密码,程序执行结束后会输出相应的出列结点的顺序,亦即其编号。
约瑟夫环实习报告

实习报告:约瑟夫环实验一、实习背景约瑟夫环问题是一个经典的计算机科学和数学问题,起源于古罗马时期的历史故事。
问题描述了n个人围成一个圆圈,从第一个人开始报数,每数到m个人就将其删除,然后从下一个人重新开始报数,直到圈中只剩下一个人。
本实习报告旨在通过实现约瑟夫环算法,深入理解其原理和应用,并分析不同算法实现的时间和空间复杂度。
二、实习内容1. 算法实现本次实习实现了两种约瑟夫环算法的实现:迭代法和递归法。
迭代法使用循环结构模拟圆圈的过程,每轮删除指定数量的节点,直到只剩下一个节点。
递归法则利用递归函数模拟这个过程,每次递归调用删除指定数量的节点,直到只剩下一个节点。
2. 算法分析在算法分析方面,我们主要从时间复杂度和空间复杂度两个方面进行考虑。
对于迭代法,时间复杂度主要取决于删除节点的次数,每次删除操作的时间复杂度为O(1),因此总的时间复杂度为O(n)。
空间复杂度主要取决于程序的存储空间,由于使用了循环结构,空间复杂度为O(n)。
对于递归法,每次递归调用都会创建一个新的栈帧,因此空间复杂度主要取决于递归深度。
在最坏情况下,递归深度为n-1,因此空间复杂度为O(n)。
时间复杂度同样为O(n),因为每次递归调用都需要进行删除操作。
3. 实验结果我们使用Python语言实现了约瑟夫环算法,并使用Python的time模块测量了不同算法实现的时间。
实验结果显示,在n较小的情况下,迭代法和递归法的运行时间相差不大。
但随着n的增大,迭代法的运行时间逐渐优于递归法。
这是因为递归法在每次递归调用时都会创建新的栈帧,随着递归深度的增加,栈帧的创建和销毁会占用较多的时间。
三、实习心得通过本次实习,我对约瑟夫环问题有了更深入的理解。
在实现算法的过程中,我学会了如何使用循环结构和递归函数模拟圆圈的过程。
在分析算法的过程中,我学会了如何计算时间复杂度和空间复杂度,并能够根据实际情况选择合适的算法。
同时,我也认识到算法优化的重要性。
约瑟夫问题数据结构实验报告

约瑟夫问题数据结构实验报告正文:⒈引言本实验报告旨在探讨约瑟夫问题及其相关数据结构的实现。
约瑟夫问题是一个经典的数学问题,涉及到环形数据结构和循环删除等操作。
通过本次实验,我们将实现约瑟夫问题的求解算法,并对其进行性能分析。
⒉算法描述⑴问题描述约瑟夫问题描述如下:有n个人围成一圈,从某个人开始依次报数,报到m的人出圈,然后从出圈的下一个人开始重新报数,如此循环,直到剩下最后一个人。
需要实现一个算法解决以下问题:(1)给定n和m,求出最后剩下的人的编号。
(2)给定n和m,按顺序输出出圈的人的编号。
⑵算法思路本实验将使用环形链表作为数据结构存储人员编号。
首先,创建一个含有n个节点的环形链表,每个节点表示一个人的编号。
然后,按照报数规则不断遍历链表,当报数等于m时,删除当前节点,并将游标指向下一个节点。
重复此过程,直到只剩下一个节点。
最后剩下的节点即为问题的解。
⒊算法设计⑴定义数据结构为了实现约瑟夫问题的求解,我们需要设计以下数据结构:(1)Person:表示每个人的节点,包含编号和指向下一个节点的指针。
(2)CircularLinkedList:表示环形链表,包含人员总数,当前游标位置和指向第一个节点的指针。
⑵算法实现(1)创建环形链表根据输入的人员总数n,创建一个含有n个节点的环形链表,每个节点表示一个人。
初始化时,节点的编号为从1到n,指向下一个节点的指针为空。
(2)解决约瑟夫问题通过循环遍历环形链表,按照报数规则逐个删除节点,直到只剩下一个节点为止。
具体步骤如下:①初始化报数计数器count=1,游标指向链表的第一个节点。
②从游标指向的节点开始,依次报数,每报数一次,count加1.③当count等于m时,删除当前节点,并将游标指向下一个节点。
④重复步骤②和③,直到只剩下一个节点。
(3)输出解决结果根据求解约瑟夫问题的要求,输出最后剩下的人的编号或按顺序输出出圈人的编号。
⒋性能分析本算法的时间复杂度为O(nm),其中n表示人员总数,m表示报数的步长。
约瑟夫环问题

1.约瑟夫环问题(实验类型:综合型)1)问题描述:有编号为1, 2…n 的 n 个人按顺时针方向围坐一圈,每人持有一个正整数密码。
开始给定一个正整数 m,从第一个人按顺时针方向自1开始报数,报到m者出列,不再参加报数,这时将出列者的密码作为m,从出列者顺时针方向的下一人开始重新自1开始报数。
如此下去,直到所有人都出列。
试设计算法,输出出列者的序列。
2)实验要求: 采用顺序和链式两种存储结构实现3) 实现提示:✧用顺序表来存储围座者的序号和密码(顺序存储结构).⏹用number 和code分别表示围座者的序号和密码.假设围座者人数为j,当前使用密码为m,开始报数者位置为s, 那么下一出列者位置为s=(s+m-1) mod j.⏹当我们要在线性表的顺序存储结构上的第i个位置上插入一个元素时,必须先将线性表的第i个元素之后的所有元素依次后移一个位置,以便腾空一个位置,再把新元素插入到该位置。
若要删除第i个元素时,也必须把第i个元素之后的所有元素前移一个位置。
✧用链式存储解决此问题时可以采用循环链表.4)注意问题:顺序存储和链式存储实现此算法时计算出列位置的不同方法,人员出列后所做操作的区别。
#include<stdio.h>#include<stdlib.h>typedef struct Node{int key;//密码int num;//编号struct Node *next;}Node,*Link;void InitList(Link &L){//创建空链表L=(Node*)malloc(sizeof(Node));if(!L)exit(1);L->key=0;L->next=L;}void Creatlinklist(int n,Link&L){//初始化链表Link p,q;q=L;for(int i=1;i<=n;i++){p=(Node*)malloc(sizeof(Node));if(!p)exit(1);scanf("%d",&p->key);p->num=i;L->next=p;L=p;}L->next=q->next;free(q);}Link Locate_m(Link &p,int m){//找到第m个Link q;for(int j=1;j<m;j++)p=p->next;q=p->next;m=q->key;return q;}void Delete_m(Link &L,Linkp,Link q){//删除第m个p->next=q->next;free(q);}int main(){Link L,p,q;int n,m;L=NULL;InitList(L);//构造一个只有头节点的空链表printf("输入初始密码:");scanf("%d",&m);//初始密码为m printf("输入总人数:");scanf("%d",&n);//总人数为nprintf("输入每个人手中的正整数密码:");Creatlinklist(n,L);//建立约瑟夫环p=L;printf("出列者顺序为:") ;for(int i=1;i<=n;i++){q=Locate_m(p,m);//找到第m个printf("%d ",q->num);Delete_m(L,p,q);//删除第m个}}5)实验心得:大部分的时间都用在了编程上,主要是因为C语言掌握的问题,C语言基础不好特别是对于C语言中链表的一些定义和基本操作不够熟练,导致在编程过程中还要不断的拿着c语言的教材查找,所以今后还要对C语言多练习,多动手,多思考。
joseph问题总结与体会

约瑟夫问题(Josephus Problem)是一个经典的数学和计算机科学问题,它描述了一个有n个人围成一圈,从第一个人开始报数,报到m的人出圈,然后从下一个人开始继续报数,直到所有人都出圈。
这个问题可以用递归或循环的方法解决。
以下是使用Python实现的约瑟夫问题的递归解法:
```python
def josephus(n, m):
if n == 1:
return 0
else:
return (josephus(n - 1, m) + m) % n
n = int(input("请输入总人数:"))
m = int(input("请输入报数间隔:"))
result = josephus(n, m)
print("最后出圈的人是第{}个人。
".format(result + 1))
```
通过这个问题,我们可以体会到以下几点:
1. 递归是一种强大的编程技巧,可以让代码更简洁、易读。
但需要注意的是,递归可能会导致栈溢出,因此在实际应用中要注意控制递归的深度。
2. 约瑟夫问题可以看作是一个循环结构的问题,但在递归解法中,我们将其转化为了递归调用。
这说明在解决问题时,可以尝试多种方法,找到最适合自己的解决方案。
3. 约瑟夫问题还可以用其他数据结构(如队列)来解决,这进一步说明了编程问题的解决方法是多样的,需要根据具体问题来选择合适的方法。
最新实验一约瑟夫问题实验报告

最新实验一约瑟夫问题实验报告实验目的:探究约瑟夫问题(Josephus Problem)的数学规律及其在不同参数下的表现,验证相关算法的效率和准确性。
实验背景:约瑟夫问题是一个著名的理论问题,源自于罗马时代的一个传说。
问题可以描述为:n个人围成一圈,从第一个人开始报数,每数到第m个人,该人出圈,然后从下一个人重新开始报数,如此循环,直到所有人出圈。
本实验旨在通过编程模拟这一过程,并分析结果。
实验方法:1. 采用编程语言(如Python)编写约瑟夫问题的模拟程序。
2. 设定不同的n和m值,运行程序,记录每个人的出圈顺序及最后剩下的人的位置。
3. 分析不同n和m值下的出圈顺序规律。
4. 对比不同算法(如递归法、迭代法)的运行时间,评估效率。
实验步骤:1. 初始化参数:确定模拟的总人数n和报数间隔m。
2. 创建一个循环队列模拟人们围成的圈。
3. 通过循环和条件判断模拟报数和出圈过程。
4. 记录每次出圈的人的编号和最终剩下的人的位置。
5. 改变n和m的值,重复步骤1至4,收集多组数据。
6. 分析数据,寻找出圈规律。
7. 对模拟过程进行计时,比较不同算法的运行时间。
实验结果:1. 通过大量实验数据,发现当n和m的值较小时,可以直观看出出圈顺序的规律。
2. 随着n和m值的增大,出圈顺序变得更加复杂,但依然存在一定的规律性。
3. 实验中使用的迭代法在处理大规模数据时,相比递归法具有更高的效率,递归法在深度较大时可能会导致栈溢出。
4. 通过图表展示了不同n和m值下,最后剩下的人的位置的概率分布。
实验结论:1. 约瑟夫问题的出圈顺序并非完全随机,存在一定的数学规律。
2. 迭代法在解决大规模约瑟夫问题时更为高效和稳定。
3. 本实验为进一步研究约瑟夫问题提供了实验数据和算法优化方向。
建议:对于未来的研究,可以尝试将约瑟夫问题推广到更多变种,如双向报数、不同方向报数等,以及探索其在实际问题中的应用,如网络协议设计、资源分配等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实习3:约瑟夫(Josephus)问题
1、问题描述
设编号为1,2,……,n(n>0)的n 个人按顺时针方向围坐一个圆圈,从第1 个人开始顺时针方向自1起顺序报数,报数到 m 为止,报数为 m 的人出列,然后从他的下一个人开始重新报数,报数为 m 的人又出列,……,直到所有的人全部出列为止。
设计算法求n 个人出圈的次序。
2、基本要求
(1)采用不带头结点的循环链表作为存储结构。
(2)对任意n个人,密码m,实现约瑟夫问题。
(3)出圈人员的编号依次输出。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Josephus {
public static void main(String[] args) throws IOException { System.out.println("输入人数:");
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
int inCount = Integer.parseInt(input.readLine());
CycLink cyclink=new CycLink();
cyclink.setLen(inCount);
cyclink.createLink();
System.out.println("每个人的编码为:");
cyclink.show();
System.out.println("输入第一个计算的号码:");
BufferedReader inp = new BufferedReader(new InputStreamReader(System.in));
int inCo = Integer.parseInt(inp.readLine());
cyclink.setK(inCo);
System.out.println("输入删除号码:");
BufferedReader inpu = new BufferedReader(new InputStreamReader(System.in));
int inC = Integer.parseInt(inpu.readLine());
cyclink.setM(inC);
cyclink.play();
}
}
class Child
{
int no;
Child nextchild=null;
public Child(int no)
{
this.no=no;
}
}
class CycLink
{
Child firstChild=null;
Child temp=null;
int len=0;
int k=0;
int m=0;
public void setLen(int inCount) {
this.len=inCount;
}
public void setK(int k)
{this.k=k;}
public void setM(int m)
{this.m=m;}
public void play()
{
Child temp=this.firstChild;
for(int i=1;i<k;i++)
{
temp=temp.nextchild;
}
System.out.println("出局顺序为 ");
while (this.len!=1){
for(int j=1;j<m;j++)
{
temp=temp.nextchild;
}
Child temp2=temp;
while(temp2.nextchild != temp)
{
temp2=temp2.nextchild;
}
temp2.nextchild=temp.nextchild;
System.out.println(temp.no);
temp=temp.nextchild;
this.len--;}
System.out.println("最后出圈 "+temp.no); }
public void createLink()
{
for(int i=1;i<=len;i++)
{
if(i==1){
Child ch=new Child(i);
this.firstChild=ch;
this.temp=ch;
}else
{
if(i==len)
{
Child ch=new Child(i);
temp.nextchild=ch;
temp=ch;
temp.nextchild=this.firstChild;
}
else
{
Child ch=new Child(i);
temp.nextchild=ch;
temp=ch;
}
}
}
}
public void show()
{
Child temp=this.firstChild;
do{
System.out.println(temp.no);
temp=temp.nextchild;
}while(temp != this.firstChild );
} }。