Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
创建节点
package com.m.demo5;
public class Node {
public int id;
public Node next;
public Node(int id) {
this.id = id;
}
@Override
public String toString() {
return "Node [id=" + id + "]";
}
}
Josephu类
package com.m.demo5;
public class Josephu {
Node first=null;//标记第一个位置,后续不会移动,所以需要一个temp
//创建一个num大小的约瑟夫环
public void createJosephu(int num) {
Node temp=first;
if(num<1) {
System.out.println("输入不符合");
return;
}
for(int i=1;i<=num;i++) {
Node n=new Node(i);
// System.out.println(n);
if(i==1) {//创建第一个环,第一个数的时候,让first指向自己
first=n;//先创建第一节点,然后让temp辅助操作
first.next=first;
temp=first;
}else {//其他时候,让temp移动连接
temp.next=n;
n.next=first;
temp=n;
}
}
}
// 显示约瑟夫环
public void show() {
Node temp=first;
if(temp==null) {
System.out.println("没有节点");
return;
}
while(true) {
System.out.println(temp);
if(temp.next==first) {//遇到最后一个节点的时候就退出循环了,所以将打印写在最前面,防止最后一个节点漏打
break;
}
temp=temp.next;
}
}
// 创建出队
/**
* 需要一个temp节点一直在first节点的前一个,做为环的最后一个
* @param startIndex 从第几个节点开始,也就是第几个节点作为first节点 需要通过这个来移动first节点的位置
* @param m 表示节点报的数 移动m-1个,first指向的节点出队
* @param nums 表示约瑟夫环的大小,用来初始化判断输入
*/
public void outQueueJosep(int startIndex,int m,int nums) {
if(first==null) {
System.out.println("空环");
return;
}
if(startIndex>nums||startIndex<1) {
System.out.println("输入的参数不对");
return;
}
//确定first的位置
for(int i=0;i<startIndex-1;i++) {
first=first.next;
}
// 确定在这个情况下,环最后的一个节点 temp;
Node temp=first;
while(true) {
if(temp.next==first) {
break;
}
temp=temp.next;
}
// 开始出队
while(true) {
if(temp==first) {//当temp==first的时候,说明环中只有一个节点了
break;
}
// 通过报的数开始移动temp和first,first指向的出队
for(int i=0;i<m-1;i++) {//m-1:因为节点本身要报数
first=first.next;
temp=temp.next;
}
System.out.println(first);
first=first.next;
temp.next=first;
}
System.out.println(temp);
}
}
测试类
package com.m.demo5;
public class test {
public static void main(String[] args) {
Josephu j=new Josephu();
j.createJosephu(5);
j.show();
System.out.println("=========");
j.outQueueJosep(1, 2, 5);
}
}