背景故事不做介绍,着重点在于约瑟夫环的逻辑。
代码中:fixedStepRemove(int start , int step)是约瑟夫环的逻辑。
package com.kali.structure.josephu;
/**
* 约瑟夫环问题:
* 1.创建一个环形链表(无头节点)
* 2.确定一个起始位置start,设置步长step,从start开始(含start)从1开始计数,
* 达到step将该位置的节点剔除
*/
public class TestJosephus {
public static void main(String[] args) {
CircleLinked cir = new CircleLinked(15);
cir.showLinked();
System.out.println("出列顺序");
cir.fixedStepRemove(1,3);// 2->4->1->5->3
}
}
class CircleLinked{
private Node first;
public CircleLinked() {
}
public CircleLinked(int num){
add(num);
}
/**
* 按照固定步长删除节点
* @param start 起始
* @param step 步长
* 思路:
* 用一个辅助指针index总是指向头部,cache跟随index之后并记录index的前一个位置,方便删除
*/
public void fixedStepRemove(int start, int step){
if(first == null || start < 1){
System.out.println("输入数据不正确");
return;
}
Node index = first;
/*找到起始位置,即start指向的节点*/
int x = 0;
while (x < start - 1) {
index = index.next;
x ++;
}
while(index.next != index){
//临时存储index的前一个节点
Node cache = index;
for(int i = 1;i < step;i++){
//每次循环,cache跟随index移动,但总在其后,for循环结束,index找到位置
cache = index;
index = index.next;
}
//打印已找到的index节点
System.out.println("---> " + index.id + "\t出列 " + index);
//更新指针,目的:删除刚找到的index节点
cache.next = index.next;
index = cache.next;
}
//while循环结束链表剩余一个节点,即为存活
System.out.println("---> " + index.id + "\t出列 " + index + "--->last");
}
public void add(int num){
if(num < 1){
System.out.println("至少为1");
return;
}
Node current = null;
for(int i = 1;i <= num;i ++){
if(i == 1){
first = new Node(i);
first.next = first;
current = first;
}else{
current.next = new Node(i);
current = current.next;
current.next = first;
}
}
}
public void showLinked(){
if(first == null){
System.out.println("环形链表为空");
return;
}
Node index = first;
while (true) {
if(index.next == first){
System.out.println(index);
break;
}else {
System.out.println(index);
}
index = index.next;
}
}
}
class Node{
public int id;
public Node next;
public Node() {
}
public Node(int id) {
this.id = id;
}
@Override
public String toString() {
return "Node{" +
"id=" + id +
'}';
}
}