• 约瑟夫问题
    • 问题来历
    • 循环链表进行模拟
    • 思路

约瑟夫问题

问题来历

据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决。Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

循环链表进行模拟

因为约瑟夫问题是一个环状,因此又被称为约瑟夫环,结构与循环链表相似,因此可以用循环链表进行模拟。

思路

  • 创建节点

    class Person
    {//序号private int num;//后继指针,指向下一个节点private Person next;public Person(int num) {this.num = num;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public Person getNext() {return next;}public void setNext(Person next) {this.next = next;}
    }
    
  • 创建一个单向的环形链表

    1. 先创建第一个头节点,并让first指针指向该节点,next指针指向本身,形成环状。

    2. 后面每创建一个新的节点,就把其加到已有的环形链表中。

    /*** 单向的环形链表*/
    class CircleSingleLinkedList
    {/*** 创建一个first节点*/private Person first;/*** 添加节点构建环形链表* @param nums 要创建的节点个数*/public void addPerson(int nums){if (nums < 1){System.out.println("nums值不正确!");return;}//帮助构建环形链表Person temp = null;//使用for来创建我们的环形链表for (int i = 1; i <= nums ; i++){//根据编号创建节点Person person = new Person(i);//头节点if (i == 1){first = person;//构成环状first.setNext(first);//让指针指向第一个节点temp = first;continue;}temp.setNext(person);person.setNext(first);temp = person;}}
    }
    
  • 遍历环形链表

    1. 先让一个辅助指针temp指向first头节点
    2. 通过while循环遍历该环形链表
    public void list()
    {if (first == null){System.out.println("空链表");return;}//头节点不能动,用辅助指针来实现遍历Person temp = first;while (true){System.out.printf("编号:%d\n",temp.getNum());//遍历完毕if (temp.getNext() == first){break;}//指针后移temp = temp.getNext();}
    }
    
  • 计算各个节点出表顺序

    1. 创建一个辅助指针end指向链表的最后一个节点

    2. 根据起始报数位置startNum,让first和end指针同时移动startNum-1次

    3. 开始报数,每次报数让first和end指针向后移动countNums-1次

    4. 最后first指针指向的节点就是要出表的节点

    5. 移出该节点,重复34步骤。

    /*** 根据用户的输入计算出人出圈的顺序* @param startNum     表示从第几个人开始报数* @param countNums    表示每次数几次* @param personNums  表示最初有多少人*/
    public void play(int startNum,int countNums,int personNums)
    {if (first == null || startNum < 1 || startNum > personNums){System.out.println("参数输入有误,请重新输入");return;}//创建辅助指针Person end = first;//开始报数之前让end指针指向最后一个节点while (true){if (end.getNext() == first){break;}end = end.getNext();}//报数前让first和end根据startNum进行校准for (int i = 0; i < startNum - 1; i++){first = first.getNext();end = end.getNext();}//报数时,让first和end指针同时移动(countNums-1)次while (true){//圈中只有一个节点if (end == first){break;}for (int i = 0; i < countNums - 1; i++){first = first.getNext();end = end.getNext();}System.out.printf("出圈号码:%d\n",first.getNum());first = first.getNext();end.setNext(first);}System.out.printf("最后留在圈中的号码是:%d\n",first.getNum());
    }
    

测试

public class Josephu
{public static void main(String[] args) {CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();//添加节点circleSingleLinkedList.addPerson(6);//遍历链表circleSingleLinkedList.list();//计算出圈顺序并输出circleSingleLinkedList.play(1,5,6);}
}
-------------------------------------------------------------------------------------------------------------------
//输出结果:
编号:1
编号:2
编号:3
编号:4
编号:5
编号:6
出圈号码:5
出圈号码:4
出圈号码:6
出圈号码:2
出圈号码:3
最后留在圈中的号码是:1
5->4->6->2->3->1

如有错误或不足欢迎评论指正。

数据结构:循环链表解决约瑟夫问题相关推荐

  1. c语言循环链表约瑟夫问题的时间复杂度,用单向循环链表解决约瑟夫问题算法优劣性分析.doc...

    用单向循环链表解决约瑟夫问题算法优劣性分析 用单向循环链表解决约瑟夫问题算法优劣性分析 摘要: 首先由简单问题引入约瑟夫问题,然后用单向循环链表解决约瑟夫问题,最后对模拟方法及数学方法的优劣性进行分析 ...

  2. 循环链表解决约瑟夫环问题

    约瑟夫环问题可以简单的使用数组的方式实现,但是现在我使用循环链表的方法来实现,因为上午看到一道面试题规定使用循环链表解决约瑟夫环问题. 什么是约瑟夫环? "约瑟夫环是一个数学的应用问题:已知 ...

  3. 使用循环链表解决约瑟夫环问题

    1.问题来源: 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一 ...

  4. 循环链表解决约瑟夫问题(简化版)

    http://blog.csdn.net/jw903/article/details/38965477 约瑟夫环是一个经典的数学的应用问题:已知N个人(以编号1,2,3...N分别表示)围坐在一张圆桌 ...

  5. 【C语言】循环链表解决约瑟夫环问题

    好玩的约瑟夫环:有M个人,编号分别为1到M,玩约瑟夫环游戏,最初时按编号顺序排成队列:每遍游戏开始时,有一个正整数报数密码N,队列中人依次围坐成一圈,从队首的人开始报数,报到N的人出列,然后再从出列的 ...

  6. 《恋上数据结构第1季》单向循环链表、双向循环链表以及约瑟夫环问题

    循环链表(CircleList) 链表的接口设计 单向循环链表 单向循环链表完整源码 双向循环链表 双向循环链表完整源码 双向循环链表解决约瑟夫环问题 如何发挥循环链表的最大威力? 静态链表 数据结构 ...

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

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

  8. 【数据结构作业—01】用单循环链表解决约瑟夫问题

    实验作业一:线性表(链表) 1. 用单循环链表解决约瑟夫问题. 问题描述: 一个旅行社要从n个旅客中选出一名旅客,为他提供免费的环球旅行服务.旅行社安排这些旅客围成一个圆圈,从帽子中取出一张纸条,用上 ...

  9. Java数据结构单向循环链表实现约瑟夫问题(丢手绢)

    环形链表 实例:使用环形链表解决约瑟夫问题(丢手绢) 构建一个单向环形链表思路 ​ 1)先创建第一个节点,让first指向该节点,并形成环形 ​ 2)加入环形链表 遍历环形链表 ​ 1)先让一个辅助指 ...

最新文章

  1. java基础===点餐系统
  2. visual studio 自动整理代码
  3. 给书配代码-电力经济调度(1):基于拉格朗日及运筹规划方法的经济调度算法
  4. MySQL日志分类及性能分析你应该知道的知识
  5. Asp.NET Core 一个接口的多个实现如何通过 DI 注册?
  6. ssm使用全注解实现增删改查案例——mybatis-config.xml
  7. 【C++模板】特化与偏特化 template [partial] specialization
  8. Log4j CVE-2021-44228后续-CVE-2021-45046,CVE-2021-45105
  9. python 防破解_Python 程序员如何防止数据被修改?
  10. 如何自定义安装mysql_安装MySQL
  11. OSEK OS(OSEK 操作系统)
  12. 自抗扰控制(ADRC)—— 一阶系统
  13. html录音并调用讯飞语音接口,微信小程序前台调用讯飞语音识别接口
  14. Linux系统管理命令(1)accton的使用
  15. 炮兵阵地(状压dp)
  16. c语言模拟抛骰子,c语言模拟抛1000000次骰子
  17. 【Unity】基础游戏单位GameObject中常用的属性和API
  18. java double long 取值_由一道题引起的思考? java中 long 和double都是64位。为什么double表示的范围大那么多呢?...
  19. 悉尼大学理学院计算机科学,悉尼大学理学院本科申请
  20. finalshell连接ubantu

热门文章

  1. sql 中的导航函数 FIRST_VALUE, LAST_VALUE
  2. oracle中app文件夹下,Oracle Form开发之folder(文件夹)功能开发(一)
  3. tkinter笔记:scale 尺度 (莫烦python笔记)
  4. 文巾解题 面试题 01.06. 字符串压缩
  5. pytorch 笔记 :实现Dropout
  6. Python应用实战案例-pyspark库从安装到实战保姆级讲解
  7. 深度学习-清晰易懂的马尔科夫链原理介绍
  8. php 根据权重随机数,PHP根据概率产生随机数
  9. 机器学习第1天:数据预处理
  10. 知识点讲解七:Python中的异常处理机制