约瑟夫环

特点

单向循环链表

描述

N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。
分析:
(1)由于对于每个人只有死和活两种状态,因此可以用布尔型数组标记每个人的状态,可用true表示死,false表示活。
(2)开始时每个人都是活的,所以数组初值全部赋为false。
(3)模拟杀人过程,直到所有人都被杀死为止。

代码实现

  1. /**
  2. * @author laoduan
  3. * @create 2020-04-09-22:27
  4. */
  5. public class josepfu {
  6. public static void main(String[] args) {
  7. CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
  8. circleSingleLinkedList.addBoy(25);
  9. // circleSingleLinkedList.showboy();
  10. circleSingleLinkedList.josepfu(1, 2, 25);
  11. }
  12. }
  13. //创建一个环形的单向列表
  14. class CircleSingleLinkedList {
  15. private Boy first = null;
  16. //添加小孩节点,组成环形链表
  17. public void addBoy(int nums) {
  18. if (nums < 1) {
  19. System.out.println("nums的值不正确");
  20. return;
  21. }
  22. Boy curBoy = null;
  23. //用for来创建环形链表
  24. for (int i = 1; i <= nums; i++) {
  25. Boy boy = new Boy(i);
  26. //如果是第一个小孩
  27. if (i == 1) {
  28. first = boy;
  29. first.setNext(first);
  30. curBoy = first;//让curBoy指向第一个小孩
  31. } else {
  32. curBoy.setNext(boy);
  33. boy.setNext(first);
  34. curBoy = boy;
  35. }
  36. }
  37. }
  38. //遍历当前环形链表
  39. public void showboy(){
  40. if(first==null){
  41. System.out.println("没有小孩");
  42. return;
  43. }
  44. //first不能动,要用辅助指针
  45. Boy curBoy =first;
  46. while (true){
  47. System.out.printf("当前小孩的编号%d\n",curBoy.getNo());
  48. if(curBoy.getNext()==first){
  49. //说明循环完毕
  50. break;
  51. }else {
  52. curBoy=curBoy.getNext();
  53. }
  54. }
  55. }
  56. //约瑟夫
  57. public void josepfu(int startNo,int n,int nums){
  58. if (first==null||startNo<1||startNo>nums){
  59. System.out.println("参数有误");
  60. return;
  61. }
  62. Boy helper = first;
  63. while (true){
  64. if(helper.getNext()==first){
  65. break;
  66. }
  67. helper=helper.getNext();
  68. }
  69. for(int j=0;j<startNo-1;j++){
  70. first=first.getNext();
  71. helper=helper.getNext();
  72. }
  73. while (true){
  74. if(helper==first){
  75. break;
  76. }
  77. for (int x=0;x<n-1;x++){
  78. first=first.getNext();
  79. helper=helper.getNext();
  80. }
  81. System.out.printf("出圈的小孩编号为%d\n",first.getNo());
  82. first=first.getNext();
  83. helper.setNext(first);
  84. }
  85. System.out.printf("最后剩下的小孩是%d\n",first.getNo());
  86. }
  87. }
  88. //创建一个boy类,表示一个结点
  89. class Boy {
  90. public int getNo() {
  91. return no;
  92. }
  93. public void setNo(int no) {
  94. this.no = no;
  95. }
  96. public Boy getNext() {
  97. return next;
  98. }
  99. public void setNext(Boy next) {
  100. this.next = next;
  101. }
  102. public Boy (int no ){
  103. this.no = no;
  104. }
  105. private int no;
  106. private Boy next;
  107. }