原文地址:https://blog.csdn.net/guorui_java/article/details/106155636
一、环环链表
环形链表是另一种形式的链表存储结构,它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
二、约瑟夫问题
三、创建环形链表

3.1 构建一个单向的环形链表思路:
先创建第一个节点,让first指向该节点,并形成环形
-后面我们没创建一个新节点,就把当前节点加入到已有的环形链表中即可
3.2 遍历环形链表:
先让一个辅助指针(遍历)curBoy,指向first节点
- 然后通过一个while循环遍历该环形链表即可 curBoy.next = first 结束
四、小孩出圈问题分析
五、代码实现
5.1 实体类
```java package com.guor.linkedlist.josepfu;
public class Boy { private int no; private Boy next;//默认空 public Boy(int no){ this.no = no; }
public int getNo() {return no;}public void setNo(int no) {this.no = no;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}
}
<a name="mY1XC"></a>## 5.2 环形链表方法类```javapackage com.guor.linkedlist.josepfu;public class CircleSingleLinkedList {//创建一个first节点,当前没有编号private Boy first = null;//添加小孩节点,构建一个环形链表public void addBoy(int nums){//nums做一个数据校验if(nums<1){System.out.println("nums的值不正确。");return;}//辅助指针,构建环形链表Boy curBoy = null;//使用for循环来创建环形链表for(int i = 1;i<= nums;i++){//根据编号创建小孩节点Boy boy = new Boy(i);//第一个小孩比较特别if(i==1){first = boy;first.setNext(first);//构成一个环curBoy = first;//让curboy指向第一个小孩}else{curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}public void showBoy(){//链表是否为空if(first == null){System.out.println("链表为空");return;}//因为first不能动,所以使用一个辅助指针完成遍历Boy curBoy = first;while(true){System.out.printf("小孩的编号 %d \n",curBoy.getNo());if(curBoy.getNext() == first){break;}curBoy = curBoy.getNext();}}//根据用户的输入,计算出小孩出圈的顺序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.getNext() == first){break;}helper = helper.getNext();}//加入startNo不是1,先让first和helper移动k-1次for (int i = 0; i < startNo - 1; i++) {first = first.getNext();helper = helper.getNext();}//当小孩报数之前,让first和helper指针同时移动countNum次,然后出圈//这里是一个循环的操作,直到圈中只有一个节点while(true){if(helper == first){//说明圈中只有一个节点break;}//让first、helper同时移动countNum- 1for (int i = 0; i < countNum - 1; i++) {first = first.getNext();helper = helper.getNext();}//这是first指向的节点就是要出圈的小孩节点System.out.printf("小孩%d出圈 \n",first.getNo());//这是将first指向的小孩节点出圈first = first.getNext();helper.setNext(first);}System.out.printf("最后留在圈中的小孩编号%d \n",first.getNo());}}
5.3 测试类
package com.guor.linkedlist.josepfu;public class Josepfu {public static void main(String[] args) {//构建环形链表和遍历是否OKCircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();circleSingleLinkedList.addBoy(5);//加入5个小孩节点circleSingleLinkedList.showBoy();//测试小孩出圈circleSingleLinkedList.countBoy(1,2,5);//2,4,1,5,3}}
六、控制台输出

