05--约瑟夫问题【单项环形链表应用】
图形示例:
1 //定义Boy类,每一个Boy类的对象都是一个节点
2 class Boy{
3 //定义小孩id
4 private int id; //值域
5
6 //创建构造器初始化值域
7 public Boy(int id) {
8 this.id = id;
9 }
10
11 private Boy next; //指针域 -->指向下一个节点
12
13 public int getId() {
14 return id;
15 }
16
17 public void setId(int id) {
18 this.id = id;
19 }
20
21 public Boy getNext() {
22 return next;
23 }
24
25 public void setNext(Boy next) {
26 this.next = next;
27 }
28
29 }
1 //定义环形链表类,用于管理生成的节点对象
2 class CircleSingleLinkedList{
3 //第一个节点
4 Boy firstBoy = null;
5
6 //根据传入的数字n,添加n个孩子节点
7 public void add(int n) {
8 //参数合法性校验
9 if (n < 1) {
10 System.out.println("n为小于1的数字,不合法");
11 return;
12 }
13 //定义辅助指针进行遍历【因为第一个小孩节点不能动】
14 Boy tmpBoy = null;
15 for(int i = 1; i <= n; i++) {
16 Boy boy = new Boy(i);
17 //特殊情况之只添加一个孩子节点
18 if (i == 1) {
19 firstBoy = boy; //建立链接
20 boy.setNext(firstBoy); //构成环
21 tmpBoy = firstBoy; //辅助节点赋值
22 }else {
23 tmpBoy.setNext(boy);
24 boy.setNext(firstBoy);
25 //向后移动,继续遍历添加节点
26 tmpBoy = tmpBoy.getNext();
27 }
28 }
29 }
30
31 /**
32 * @param startBoy 从第几个小孩儿开始数数
33 * @param eachCount 每次数几个小孩【从当前小孩开始数】
34 * @param totalBoy 总的小孩的个数
35 */
36 public void josephu(int startBoy,int eachCount,int totalBoy) {
37 //参数合法性校验
38 //空链表、从第(小于1个)小孩开始、开始的小孩数 > 总的小孩数
39 if (firstBoy == null || eachCount < 1 || startBoy < 1 || startBoy > totalBoy) {
40 System.out.println("参数有误");
41 return;
42 }else {
43 //定义辅助指针,指向最后一个小孩
44 Boy helper = firstBoy;
45 while(true) {
46 //找到了最后要给小孩 --> 指向第一个小孩
47 if (helper.getNext() == firstBoy) {
48 break;
49 }
50 //继续往后寻找
51 helper = helper.getNext();
52 }
53
54 //定位到startBoy:
55 //firstBoy、helper均移动 eachCount - 1 次
56 for(int i = 0; i < startBoy - 1; i++) {
57 firstBoy = firstBoy.getNext();
58 helper = helper.getNext();
59 }
60 //循环移动,依次出圈
61 while(true) {
62 //说明就剩最后一个出圈的小孩了
63 if (firstBoy == helper) {
64 System.out.println(helper.getId()); //等同于 firstBoy.getId()
65 helper.setNext(null); //出圈
66 break;
67 }else {
68 //移动到待出圈孩子的位置
69 for(int i = 0; i < eachCount - 1; i++) {
70 firstBoy = firstBoy.getNext();
71 helper = helper.getNext();
72 }
73 //此时:firstBoy代表的就是要出圈的孩子
74 System.out.printf("%d --> ",firstBoy.getId());
75 //后移
76 firstBoy = firstBoy.getNext();
77 helper.setNext(firstBoy);
78 }
79 }
80 }
81 }
82
83 //遍历环形单链表
84 public void list() {
85 if (firstBoy == null) {
86 System.out.println("单链表为空");
87 return;
88 }else {
89 //定义辅助节点帮助遍历
90 Boy tmp = firstBoy;
91 while(tmp.getNext() != firstBoy) {
92 System.out.print(tmp.getId() + " --> ");
93 //继续遍历
94 tmp = tmp.getNext();
95 }
96 //此时临时节点代表第一个孩子节点的上一个节点
97 System.out.print(tmp.getId());
98 }
99 }
100
101 }
1 //约瑟夫/环 问题
2 public class JosephuDemo {
3
4 public static void main(String[] args) {
5 CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
6 circleSingleLinkedList.add(5);
7 circleSingleLinkedList.list();
8 System.out.println();
9 System.out.println("约瑟夫问题演示: --> ");
10 circleSingleLinkedList.josephu(1, 2, 5);
11 }
12
13 }