约瑟夫问题
-
约瑟夫问题
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 -
思路
用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。
/**
* @author zl
* @create 2020--09--03--19:28
*/
public class Josephu {
public static void main(String[] args) {
CircleSingleLinkedList linkedList = new CircleSingleLinkedList();
linkedList.addBoy(5);
linkedList.showBoy();
linkedList.countBoy(2,2,5);
}
}
//定义环形列表
class CircleSingleLinkedList {
//创建一个first节点,用于存储第一个节点
private BoyNode first = null;
public void addBoy(int nums) {
if (nums < 1) {
System.out.println("输入的值不正确");
return;
}
//这个是真正的列表
BoyNode curNode = null;//用于构建环形列表
for (int i = 1; i <= nums; i++) {
BoyNode boyNode = new BoyNode(i);
if (i == 1) {
first = boyNode;
first.next = first;
curNode = first;
} else {
curNode.next = boyNode;
boyNode.next = first;
curNode = boyNode;
}
}
}
//查看链表
public void showBoy() {
if (first == null) {
System.out.println("链表为空");
}
BoyNode temp = first;
while (true) {
if (temp.next == first) {
break;
}
System.out.printf("小孩编号为%d\t", temp.no);
temp = temp.next;
}
System.out.printf("小孩编号为%d\t",temp.no);
System.out.println();
}
/**
* @param startNo 从第几个孩子开始数
* @param countNum 每次数几个数
* @param nums 表示最初有几个孩子在圈中
*/
public void countBoy(int startNo, int countNum, int nums) {
if (first == null || startNo < 1 || startNo > nums) {
System.out.println("输入数据有误");
return;
}
BoyNode temp = first;
//让temp指向最后一个节点,为了结束循环
while (true) {
if (temp.next == first) {
break;
}
temp = temp.next;
}
//报数前,让first和temp同时移动k-1次,移动到指定的第几个孩子开始的数
for (int i = 0; i < startNo - 1; i++) {
first = first.next;
temp = temp.next;
}
while (true) {
//结束循环条件
if (temp == first) {
break;
}
for (int j = 0; j < countNum - 1; j++) {
first = first.next;
temp = temp.next;
}
//找到出圈的节点
System.out.println("出圈"+first.no);
//让出圈的节点 = 下一个节点
first = first.next;
//将出圈的前一个节点指向出圈的下个节点
temp.next = first;
}
System.out.println("最后出圈"+first.no);
}
}
//定义节点
class BoyNode {
public int no;
public BoyNode next;
public BoyNode(int no) {
this.no = no;
}
}