Java_Josephus问题约瑟夫环详细分享先看代码再分享1.约瑟夫环代码以下是完整代码和注释publicclassLinkedNode{//设置私有对象privateT数据;//接下来定义通用数据字段privateLinkedNode;//定义后续引用字段publicLinkedNode(){//无参构造器,构造一个空节点data=null;next=null;}publicLinkedNode(Telement){//构造函数,构造一个数据字段为元素值的节点data=element;next=null;}publicTgetData(){//获取数据字段返回数据的值;}publicvoidsetData(Tdata){//设置data字段数据值this.data=data;}publicLinkedNodegetNext(){//获取下一个值returnnext;}publicvoidsetNext(LinkedNodenext){//设置下一个值this.下一个=下一个;}}public类数据类型{privateintid;//存储我们的idprivateintpassword;//存储我们的密码publicdatatype(){//构造一个无参构造函数,构造一个空节点}publicdatatype(intid,intpassword){//构造函数,让它与导入的内容连接this.id=id;这个.password=密码;}publicintgetId(){//获取我们的id值returnid;}publicvoidsetId(intid){//设置我们的id值this.id=id;}publicintgetPassword(){//获取我们的密码returnpassword;}publicvoidsetPassword(intpassword){//设置我们的密码this.password=password;}}导入java.util.Scanner;classCList{privateLinkedNoderear;//生成节点并定义尾指针publicCList(){rear=null;}publicLinkedNodegetRear(){返回后方;}publicvoidsetRear(LinkedNoderear){this.rear=rear;}publicTyunxingCircular(intm){if(isEmpty()){//判断是否为空thrownewRuntimeException("emptytable");}else{//如果不是空表,判断是否是一个元素if(rear.getNext()==rear){//如果只有一个元素LinkedNodecz=rear;//设置一个新的node,携带rear节点rear=null;//此时让rear的值为null,即删除这里的元素rreturncz.getData();//返回此时用来携带节点的数据域}else{//如果不是只有一个元素inta=1;//定义第一个单独的报表为1while(acz=后方。getNext();//设置新节点承载rear节点rear.setNext(rear.getNext().getNext());//让rear的引用域为上一个rear返回的下一个节点的地址直邮getData();//返回节点cz的数据域}}}publicvoidinsert(Telement){//用于表示向Joseph表中插入元素的方法LinkedNodecr=newLinkedNode(element);//设置一个新节点cr,其data字段为elementif(rear==null){//如果rear值为null,即只有一个元素rear=cr;//rear为now等于刚刚插入的新节点crrear.setNext(rear);//添加一个元素后,rear的下一个元素还在rear,形成循环}else{//如果不是元素cr.setNext(rear.getNext());//插入的元素的引用域是此时尾指针指向的元素的引用域中的地址,即此时连接到尾节点。rear.setNext(cr);//尾指针指向的元素的引用字段为crelementrear=cr;//将尾指针向后移动一位}}publicbooleanisEmpty(){//判断循环链表是否为空的方法if(rear==null)//根据rear是否为空=null判断返回值是true还是falsereturntrue;否则返回假;}}publicclassYsf{publicstaticvoidmain(String[]args){CListzx=newCList();//创建一个Clist对象Scannersr=newScanner(System.in);System.out.println("请输入圈内人数");intpeoples=sr.nextInt();//判断环内总人数System.out.println("请输入初始密码值");int密码=sr.nextInt();intjl=1;//用来跟在后面记录人数的密码值do{System.out.println("请输入"+jl+"人的密码值");intpassword0=sr.nextInt();//一一输入每个人的密码值datatypejd=newdatatype(jl,password0);//创建一个datatype节点,存储每个人及其对应的密码值zx。insert(jd);//依次向约瑟夫环中添加节点jl++;//记录数加一}while(jl<=peoples);//只要记录数不超过记录数人intb=0;while(b<人民){//当人数小于人数时datatypec=(datatype)zx.yunxingCircular(password);//添加初始密码值运行约瑟夫环System.out.println(c.getId());//输出c对象id值password=c.getPassword();//让password值更新,找到b++;//再次循环执行}}}2.什么是JosephRingJosephRing1问题是:数字是1,2,……,n个人按顺时针方向坐成一圈,每人持有一个密码。开始时选择一个正整数作为人数m的上限,从第一个人开始顺时针从1开始依次计数,报到m时停止计数。报告m的人出去,用他的密码作为新的m值,从顺时针方向的下一个人开始重新从1开始报告,以此类推,直到把所有人都列出来。3.理解约瑟夫环3.1完成节点类和数据类的定义在真正开始设计我们的约瑟夫环之前,我们需要节点类和数据类的支持,如下图LinkedNode是我们的节点类publicclassLinkedNode{//设置私有对象privateTdata;//定义通用数据字段privateLinkedNodenext;//定义后续引用字段publicLinkedNode(){//无参构造函数,构造一个空节点data=null;next=null;}publicLinkedNode(Telement){//构造函数,构造一个数据字段为元素值的节点data=element;next=null;}publicTgetData(){//获取数据字段数据返回数据的值;}publicvoidsetData(Tdata){//设置data字段数据值this.data=data;}publicLinkedNodegetNext(){//获取下一个值returnnext;}publicvoidsetNext(LinkedNodenext){//设置下一个值this.next=next;}}下面的数据类型是我们的数据类publicclassdatatype{privateintid;//存储我们的idprivateintpassword;//存储我们的密码publicdatatype(){//构造一个无参数的构造函数,构造一个空节点}publicdatatype(intid,intpassword){//构造一个函数,让它与导入的内容连接this.id=编号;日is.password=密码;}publicintgetId(){//获取我们的id值returnid;}publicvoidsetId(intid){//设置我们的id值this.id=id;}publicintgetPassword(){//获取我们的密码returnpassword;}publicvoidsetPassword(intpassword){//设置我们的密码this.password=password;}}3.2理解插入过程我们有两个步骤来帮助理解我们利用伪代码2制作图像,如下图所示接下来,我们使用图像编写代码,如下所示publicvoidinsert(Telement){//用来表示向Joseph表中插入元素的方法LinkedNodecr=newLinkedNode(element);//设置一个新节点cr,其data字段为elementif(rear==null){//如果rear值为null,即只有一个元素rear=cr;//rear此时等于新插入的新节点crrear.setNext(rear);//添加一个元素后,rear的下一个元素还是rear,形成循环}else{//如果不是元素cr.setNext(rear.getNext());//插入元素的引用域是此时尾指针指向的元素的引用域中的地址,即此时连接到尾节点。rear.setNext(cr);//此时尾指针指向元素的引用字段对于cr元素rear=cr;//将尾指针向后移动一位}}3.3理解运行过程首先我们要知道判断循环链表是否为空的方法,如下图publicbooleanisEmpty(){//用来判断是否为空循环链表为空if(rear==null)//根据rear=null是否为true判断返回值是true还是falsereturntrue;否则返回假;制作一张图片,如下图接下来我们使用图片来写代码,如下图privateLinkedNoderear;//生成节点并定义尾指针publicCList(){rear=null;}publicLinkedNodegetRear(){//获取尾指针returnrear;}publicvoidsetRear(LinkedNoderear){//设置尾指针this.rear=rear;}publicTyunxingCircular(intm){if(isEmpty()){//判断是否为空thrownewRuntimeException("emptytable");}else{//如果不是空表,判断当前是否是元素if(rear.getNext()==rear){//如果只有一个元素LinkedNodecz=rear;//设置一个新节点,携带后节点rear=null;//此时让rear的值为null,即删除这里的元素returncz.getData();//返回这个用来携带节点的数据域}else{//如果元素不止一个inta=1;//定义第一个个体数为1while(acz=rear.getNext();//设置新节点携带后方的下一个节点rear.setNext(rear.getNext().getNext());//使后方的引用域成为前一个后方地址的下一个节点returncz.getData();//返回宿主节点cz的数据域}}}3.4理解更新密码值我们用文字来理解:先把操作和更新密码分开,设置一个单独的while循环3,每次执行一次yunxingCircular,得到获取密码一次,并使密码等于获取密码,将新密码放入循环yunxingCircular和更新密码值是一个循环,所以可以实现每次密码值更新,如下图intb=0;while(b