Josephu (约瑟夫)问题
Josephu问 题为:设编号为1, 2, … n的n个人围坐- -圈,约定编号为k (1<=k<=n) 的人从1开始报数,数到
m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此
产生-一个出队编号的序列。
思路分析
用一个不带头结点的循环链表来处理Josephu问题:
先构成-一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个节点从链表中删除,算法结束。
1.创建环型链表思路图解
2.Josephu 问题思路图解
代码实现
环型单向链表
/**
* 环型单链表
*
* @author 98578
*/
public class CircleSingleLinkedList {
//起始节点
private Node first = null;
/**
* 添加节点
*
* @param num
*/
public void add(int num) {
if (num < 1) {
System.out.println("num数目有误");
return;
}
//辅助节点
Node cur = null;
for (int i = 1; i <= num; i++) {
Node node = new Node(i);
//第一个节点插入,任命为first,同时让cur
if (i == 1) {
first = node;
cur = node;
cur.setNext(first);
} else {
cur.setNext(node);
node.setNext(first);
cur = node;
}
}
}
/**
* 遍历链表
*/
public void list() {
if (first == null) {
System.out.println("===链表为空===");
}
Node temp = first;
while (true) {
System.out.println(temp);
if (temp.getNext() == first) {
break;
}
temp = temp.getNext();
}
}
/**
* 约瑟夫问题
*
* @param startNo 开始的编号
* @param countNum 数到第countNum个出圈
* @param nums 总人数
*/
public void countNode(int startNo, int countNum, int nums) {
if (first == null || startNo < 1 || startNo > nums) {
System.out.println("参数输入有误");
}
//定义辅助节点,位于环型单向链表的最后一个节点,为出圈删除做准备。
Node temp = first;
//1.先让temp位于环型单向链表的最后
for (int i = 0; i < nums - 1; i++) {
temp = temp.getNext();
}
//2.让temp与first分别移动 startNo-1个
for (int i = 0; i < startNo - 1; i++) {
first = first.getNext();
temp = temp.getNext();
}
//3.开始报数出圈
while (true) {
//只剩最后一个
if (temp == first) {
break;
}
//让temp与first分别移动 countNum-1个
for (int i = 0; i < countNum - 1; i++) {
first = first.getNext();
temp = temp.getNext();
}
System.out.println(first + "出圈");
first = first.getNext();
temp.setNext(first);
}
//输出最后保留的人
System.out.println("留到最后的节点是:" + first);
}
}
节点
public class Node {
private int no;
private Node next;
public Node(int no) {
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
@Override
public String toString() {
return "节点编号" +
"no=" + no ;
}
}
约瑟夫测试
/**
* 约瑟夫
* @author 98578
*/
public class Josepfu {
public static void main(String[] args) {
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.add(5);
circleSingleLinkedList.list();
System.out.println("===约瑟夫===");
circleSingleLinkedList.countNode(1,2,5);
}
}