问题描述:
Josephu(约瑟夫、约瑟夫环) 问题
Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数 到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由 此产生一个出队编号的序列。
提示:用一个不带头结点的循环链表来处理 Josephu 问题:先构成一个有 n 个结点的单循环链表,然后由 k 结 点起从 1 开始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从 1 开始计数,直 到最后一个结点从链表中删除算法结束。
/**
* 约瑟夫问题
*/
public class JosehuDemo {
//定义一个起始节点
private Node first;
public JosehuDemo(int total) {
if (total < 1) {
System.out.println("游戏人数有误");
return;
}
//最后一个结点
Node last = null;
//根据总人数创建链表
for (int i = 1; i <= total; i++) {
Node node = new Node(String.valueOf(i));
//第一个节点,next指向自身
if (i == 1) {
first = node;
node.next = first;
} else {
//每个节点都加在first节点的前一个位置
last.next = node;
node.next = first;
}
last = node;
}
}
/**
* @param startpostion 报数开始的位置
* @param removepostion 报数出列的位置
*/
public void start(int startpostion, int removepostion) {
if (first == null) {
System.out.println("空链表");
return;
}
if (startpostion < 1 || removepostion < 1) {
System.out.println("参数不正确");
return;
}
//移动开始节点的位置
Node cur = first;
//单链表删除,需要找到链表的上一个节点,所以定义一个辅助节点
Node pre = cur.next;
while (pre.next != first) {
pre = pre.next;
}
System.out.println("cur=" + cur + "pre=" + pre);
//移动到开始报数的位置 比如从1开始,就不用移动,2开始就是移动1位
//移动的次数startpostion-1
for (int i = 1; i < startpostion; i++) {
pre = pre.next;
}
//更新报数开始的位置
cur = pre.next;
System.out.println("更新报数位置后 cur=" + cur + "pre=" + pre);
//相等的时候,就是最后一个人
while (cur != pre) {
//报数 报数也是从1开始,移动的次数是removepostion-1
//移动完后,cur对应的节点需要出圈
for (int i = 1; i < removepostion; i++) {
cur = cur.next;
pre = pre.next;
}
System.out.println("出队列=" + cur);
//报数完毕之后,出队列
//cur移动到下一个节点
cur = cur.next;
//pre指向新的cur节点
pre.next = cur;
}
System.out.println("最后出圈=" + cur);
//全部出圈
first = null;
System.out.println("全部出圈");
}
/**
* 打印链表
*/
public void show() {
if (first == null) {
System.out.println("空链表");
return;
}
//遍历打印
Node cur = first;
while (true) {
System.out.println(cur);
cur = cur.next;
if (cur == first) {
break;
}
}
}
/**
* 定义节点
*/
public static class Node {
public String value;
public Node next;
public Node() {
}
public Node(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"value='" + value + '\'' +
'}';
}
}
}