代码
package top.snailstudy.linkedlist;
public class Josephu {
public static void main(String[] args) {
CircleSingleLinkedList list = new CircleSingleLinkedList();
list.addBoy(5);
list.showBoy();
list.countBoy(1,2,5);
}
}
class CircleSingleLinkedList{
//创建一个first节点,当前没有编号
private Boy first = null;
//添加节点,构建成环形链表
public void addBoy(int 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.setNext(first);//构成一个环
curBoy = first; //让curBoy指向第一个节点
}else{
curBoy.setNext(boy);
boy.setNext(first);
curBoy = boy;
}
}
}
//遍历环形链表
public void showBoy(){
if(first == null){
System.out.println("链表为空");
return;
}
Boy curBoy = first;
while (true){
System.out.printf("节点的编号%d\n",curBoy.getNo());
if(curBoy.getNext() == first){//遍历完毕
break;
}
curBoy = curBoy.getNext();//后移
}
}
//根据用户的输入,计算出出圈的顺序
/*
* 分析:生成一个节点出圈顺序,n=5,即有5人;k=1,从第一个人开始报数;m=2,数两下
* 创建一个辅助指针(变量)helper,事先应该指向环形链表的最后这个节点
* 当节点报数时,让first和helper指针同时的移动 m-1 次
* 这时就可以将first指向的节点出圈
* first = first.next
* helper.next = first
* 原来first指向的节点就没有任何引用,就会被回收
* startNo :表示从第几个节点开始报数
* countNum : 表示数几下
* 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.getNext() == first){//说明helper指向了最后节点
break;
}
helper = helper.getNext();
}
//报数前,先让first和helper移动 k - 1
for (int i = 0; i < startNo - 1; i++) {
first = first.getNext();
helper = helper.getNext();
}
//当节点报数时,让first和helper指针同时的移动 m-1 次
while (true){
if(helper == first){//圈中只有一个节点
break;
}
for (int i = 0; i < countNum - 1; i++) {
first = first.getNext();
helper = helper.getNext();
}
System.out.printf("节点%d出圈\n",first.getNo());
first = first.getNext();
helper.setNext(first);
}
System.out.printf("最后留在圈中的节点%d \n",first.getNo());
}
}
class Boy{
private int no; //编号
private Boy next; //指向下一个节点,默认null
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;
}
}
输出结果 节点的编号1 节点的编号2 节点的编号3 节点的编号4 节点的编号5 节点2出圈 节点4出圈 节点1出圈 节点5出圈 最后留在圈中的节点3