使用单向环形链表实现约瑟夫(Josephu)问题

1.约瑟夫(Josephu)问题描述

Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此 产生一个出队编号的序列。

2.小提示

用一个不带头结点的循环链表来处理 Josephu 问题:先构成一个有 n 个结点的单循环链表,然后由 k 结点起从 1 开 始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从 1 开始计数,直到最后一个结点从链表中删除算法结束。

3.约瑟夫(Josephu)问题—创建单向环形单链表的思路和图解

思路:
(1)先创建一个结点,让first指针指向该节点,并使first.next=first使得第一个结点自己 形成一个环,并将辅助指针指向该节点。核心代码是:

if(i==1){first=boy;//如果只有一个结点,就先自己构成一个环first.next=first;//让辅助指针curBoy指向第一个小孩curBoy=first;}

(2)后面没创建一个结点,就将该节点加入到该环形链表中,核心代码是

                curBoy.next=boy;boy.next=first;curBoy=boy;

图解:


4.约瑟夫(Josephu)问题—遍历环形单链表思路

(1)创建一个辅助指针curBoy,指向first结点
(2)然后通过while循环遍历单向环形单链表,直到curBoy.next==first结束

5.约瑟夫(Josephu)问题核心—小孩子出圈顺序思路分析

(1)举例:根据用户的输入,生成一个小孩的顺序
n=5:表示单链表中有五个结点,即初始时圈中有五个小孩
k=1:表示从第一个孩子开始报数
m=2:每次数两个人,出圈一个孩子

(2)思路分析

—创建一个helper指针,起始时指向唤醒链表的最后一个结点。
—小孩报数前,先让first指针和helper指针同时移动k-1次(因为题目不一定是从第一个孩子开始报数)
—之后小孩报数时,将first指针和helper指针同时移动m-1次
----这时可以将first指向的小孩结点同时出圈:first=first.next helper.next=first

(3)案例出圈顺序为:2–>4–>1–>5–>3

6.约瑟夫(Josephu)问题代码实现

package cn.zzw.algorithm.LinkedList;//使用单向环形链表实现约瑟夫问题
public class Josepfu {public static void main(String[] args) {//测试环形链表和遍历CircleSingleLinkedList circleSingleLinkedList=new CircleSingleLinkedList();circleSingleLinkedList.addBoy(5);circleSingleLinkedList.show();//测试小孩结点出圈顺序是否正确circleSingleLinkedList.countBoy(1,2,5);}
}//创建一个Boy类,表示一个环形链表中的一个结点
//当然可以把属性no和next设为私有,之后使用get和set方法进行访问
class Boy
{public int no;public Boy next;//表示结点的下一个结点,默认值为nullpublic Boy(int no) {this.no = no;}@Overridepublic String toString() {return "Boy{" +"no=" + no +'}';}
}//创建一个环形的单链表
class CircleSingleLinkedList
{//创建一个first结点,当前默认为null,没有后继结点private Boy first=null;//添加小孩结点,构建一个环形的链表public void addBoy(int nums){//为了防止nums不合法,对其进行数据校验if(nums<1){System.out.println("nums数据值不合法");return;}//使用辅助指针,帮助构建环形链表Boy curBoy=null;for(int i=1;i<=nums;i++){//根据编号,创建小孩结点Boy boy=new Boy(i);//如果小孩是第一个结点if(i==1){first=boy;//如果只有一个结点,就先自己构成一个环first.next=first;//让辅助指针curBoy指向第一个小孩curBoy=first;}else{curBoy.next=boy;boy.next=first;curBoy=boy;}}}//遍历当前链表public void show(){//判断当前链表是否为空if (first==null){System.out.println("当前链表为空,没有任何结点");return;}//first指针不能动,应该使用一个辅助指针完成链表的遍历Boy curBoy=first;while (true){System.out.printf("当前小孩的编号为:%d\n",curBoy.no);if(curBoy.next==first){break;}//后移辅助指针curBoy=curBoy.next;}}/**** @param startNo*           startNo表示从第几个小孩开始报数* @param countNum*           countNo表示一次数几下* @param nums*            nums表示一个圈中初始有几个孩子(结点)*///根据用户输入,指定小孩出圈的顺序,也是整个约瑟夫问题的核心public void countBoy(int startNo,int countNum,int nums){//首先进行数据校验if(first==null||startNo<1||startNo>nums){System.out.println("数据输入有误,请重新输入");return;}//创建辅助指针,帮助完成小孩出圈Boy helper=first;//开始时将辅助指针指向环形链表的最后一个结点while (true){if(helper.next==first){break;}helper=helper.next;}//因为有时题目开始报数的并不是1,所以应该先让first和helper同时移动startNo-1次for (int j=0;j<startNo-1;j++){first=first.next;helper=helper.next;}//当小孩报数时,让first和helper指针同时移动countNum-1次,然后出圈//这里是一个循环操作,直到圈里面的人数只有一个while(true){if (helper==first){//此时表示链表中只有一个结点break;}//让first指针和helper指针同时移动countNum-1次for(int j=0;j<countNum-1;j++){first=first.next;helper=helper.next;}//这时first指向的就是将要出圈的孩子System.out.printf("小孩%d出圈\n",first.no);//这时将first指向的小孩结点出圈first=first.next;helper.next=first;}System.out.printf("最后留在圈中的小孩编号%d\n",first.no);}
}

7.代码测试结果

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:D:\IntelliJ IDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=12960:D:\IntelliJ IDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;C:\Users\1\IdeaProjects\algorithm\out\production\algorithm" cn.zzw.algorithm.LinkedList.Josepfu
当前小孩的编号为:1
当前小孩的编号为:2
当前小孩的编号为:3
当前小孩的编号为:4
当前小孩的编号为:5
小孩2出圈
小孩4出圈
小孩1出圈
小孩5出圈
最后留在圈中的小孩编号3Process finished with exit code 0

五、单向环形链表---实现约瑟夫(Josephu)问题相关推荐

  1. (数据结构与算法)单向环形链表解决约瑟夫问题

    约瑟夫(Josephu)问题 Josephu问题为: 设编号为1, 2,- n的n个人围坐一圈,约定编号为k (1<=k<=n) 的人从1开始报数,数到m的那个人出列,它的下一位又从1开始 ...

  2. java模拟单链表环形链表解决约瑟夫问题

    java模拟环形链表解决约瑟夫问题 此文是观看尚硅谷韩老师的数据结构与算法学习视频整理的笔记 约瑟夫问题描述 约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算 ...

  3. 简洁明了!Java实现单向环形链表以解决约瑟夫环Josepfu问题

    文章目录 简单介绍 代码实现 简单介绍 如果把单链表的最后一个节点的指针指向链表头部,而不是指向NULL,那么就构成了一个单向循环链表,通俗讲就是让尾节点指向头结点. 单向环形链表应用场景:Josep ...

  4. 牛客题霸 [ 环形链表的约瑟夫问题] C++题解/答案

    牛客题霸 [ 环形链表的约瑟夫问题] C++题解/答案 题目描述 据说著名犹太历史学家 Josephus 有过以下故事:在罗马人占领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞 ...

  5. 约瑟夫(环)问题(Josephu)(单向环形链表)

    问题描述 代码实现 package com.atguigu.linkedlist;import com.sun.org.apache.bcel.internal.generic.NEW;/*** @创 ...

  6. 数据结构 - 链表(单向环形链表)(约瑟夫问题)

    问题如下(与分析) 构建思路 输入一个数,数到这个数的小孩出圈,出圈顺序的思路 代码实现 根据图解,来一步一步实现 //根据用户输入,计算小孩出圈顺序/**** @param startNo 表示从第 ...

  7. 双向链表、环形链表及约瑟夫问题

    一.双向链表 使用带head头的双向链表实现 - 水浒英雄排行榜管理单向链表的缺点分析: 1)单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找. 2)单向链表不能自我删除,需要靠辅助 ...

  8. java实现环形链表解决约瑟夫环问题

    什么是环形链表? 环形链表就是单向链表的基础上让链表的首尾相连,形成一个环,这就是一个循环链表. 什么是约瑟夫环问题? 约瑟夫环如下: 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数, ...

  9. 数据结构:单向环形链表

    约瑟夫问题 public class Josephus {public static void main(String[] args){SingleCircleLinkedList single = ...

最新文章

  1. Amazon SageMaker和NVIDIA NGC加速AI和ML工作流
  2. [Javascript]怎么样让公告不间断的滚动显示
  3. jQuery+css+html淘宝购物车模块
  4. push an existing repository from the command line
  5. 一个由于Pricing RFC引起的UI超时问题
  6. JSP,JSF和EL简介
  7. Asp.net禁用页面缓存的方法总结
  8. Azkaban 进程和任务监控(任务状态从MySQL同步到SqlServer)
  9. python股票_python股票 - 随笔分类 - 無碼 - 博客园
  10. html组合标题,如何组合标题关键词(影响标题的5个因素)
  11. 古诗词学习-归园田居+牧童+凉州词·其一+马诗+逢雪宿芙蓉山主人+凉州词+别董大+枫桥夜泊+滁州西涧+渔歌子+塞下曲
  12. 微信小程序--使用本地服务器进行测试开发
  13. JavaScript自动触发事件
  14. PHPStorm 显示自动换行
  15. IDEA解决Python项目如何numpy等安装包的问题
  16. yj.iOS 仿微信长按摄像点击拍照
  17. 迎难而上 数据库管理员怎样走向成功?(转)
  18. jquery中的event
  19. mysql自增不连续的问题
  20. 【答学员问】完全零基础培训IT,学习能跟的上吗?

热门文章

  1. 读“基于深度学习的图像风格迁移研究综述”有感
  2. java Excel 导入 IllegalStateException 异常处理 不同的数据类型
  3. getFields()和getDeclaredFields的区别
  4. HTML中单选框的设置,和提交按钮之间的组合
  5. JMC | 人工智能在药物发现中的应用:走进广阔的天地
  6. Failure [DELETE_FAILED_INTERNAL_ERROR]的解决办法
  7. 【问题收录】Ubuntu Starting LightDM Display Manager fail
  8. R语言绘制二维密度图
  9. R包corrplot绘图相关系数矩阵
  10. 今年1篇Science,2篇NBT,2篇MP,1篇PNAS等11篇文章,遗传发育所白洋组在植物微生物组取得系列进展!