今天用java解决了约瑟夫问题,小结一下。
问题描述:有n个小孩围成一圈,顺序排号1-n。从编号为k的小孩开始报数,报到m的小孩退出圈子,然后下一个小孩继续从1开始报数,报到m的小孩退出圈子,如此重复。问最后留下的那个小孩的编号是多少?
例:n=9,k=1,m=5
依次出列的小孩编号为:5,1,7,4,3,6,9,2。最后留下的小孩编号为8。
附上源代码:
import java.io.*;
/**
*@classname Josehu.java
*@description 约瑟夫问题
*@author 恋风 2010、4、4
*version 0.1
*copyright 恋风
*/
public class Josephus{
private static Node firstNode;//始终指向第一个节点即首节点,初始化后将不再改变
private static Node cursorNode;//游标节点,用于建立约瑟夫环和寻找数到devilNumber的节点
private static int nodeNumber;//节点个数
private static int startNumber;//开始数数的节点的编号
private static int devilNumber;//数到devilNumber的节点将出列
/**
*这是一个节点类,代表约瑟夫环上的一个节点
*/
protected static class Node{
private int number;//节点编号
private Node preNode;//父节点
private Node nextNode;//子节点
/**
*构造器
*@param nodeNumber 节点编号
*/
protected Node(int number){
this.number = number;
}
}
public static void main(String[] args){
//初始化参数
Josephus.init();
//创建约瑟夫环
Josephus.createCycle();
//打印约瑟夫环
System.out.println("小孩顺序编号如下:");
Josephus.printJosehu();
System.out.println();
//准备游戏
System.out.println("准备游戏……");
Josephus.prePlay();
//开始游戏
System.out.println("开始游戏啦!");
Josephus.play();
}
/**
*初始化参加游戏的小孩子个数、开始数数的小孩子的编号和魔鬼数字
*/
private static void init(){
//创建一个BufferedReader对象,用户读取标准输入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try{
System.out.println("请输入参加游戏的小孩子的个数:");
String s_nodes = br.readLine();
Josephus.nodeNumber = Integer.parseInt(s_nodes);
System.out.println("请输入开始数数的小孩的编号(1-"+Josephus.nodeNumber+"):");
String s_startNumber = br.readLine();
Josephus.startNumber = Integer.parseInt(s_startNumber);
System.out.println("请输入魔鬼数字(1-"+Josephus.nodeNumber+"):");
String s_devilNumber = br.readLine();
Josephus.devilNumber = Integer.parseInt(s_devilNumber);
}catch(Exception e){
System.out.println(e.getMessage());
}
}
/**
*创建约瑟夫环
*/
private static void createCycle(){
//创建约瑟夫环
for(int i = 1;i <= Josephus.nodeNumber;i++){
if(i == 1){
//创建首节点
Node node = new Node(i);
//设置firrstNode和cursorNode都指向首节点
Josephus.firstNode = node;
Josephus.cursorNode = node;
}else{
if(i == Josephus.nodeNumber){
//创建尾节点
Node node = new Node(i);
//设置尾节点的父节点为当前游标节点
node.preNode = Josephus.cursorNode;
//设置尾节点的nextNode为首节点
node.nextNode = Josephus.firstNode;
//设置首节点的父节点为尾节点
Josephus.firstNode.preNode = node;
//设置当前游标节点的nextNode为尾节点node
Josephus.cursorNode.nextNode = node;
//设置尾节点为当前游标节点
Josephus.cursorNode = node;
}else{
//创建新节点
Node node = new Node(i);
//设置新节点的父节点为当前游标节点
node.preNode = Josephus.cursorNode;
//设置当前游标节点的nextNode为新创建的节点node
Josephus.cursorNode.nextNode = node;
//设置当前新创建的节点node为当前游标节点
Josephus.cursorNode = node;
}
}
}
}
/**
*遍历约瑟夫环各节点,输出节点值
*/
private static void printJosehu(){
//创建一个Node对象,用于遍历约瑟夫环内的所有节点
Josephus.cursorNode = Josephus.firstNode;
do{
System.out.print(Josephus.cursorNode.number+" ");
Josephus.cursorNode = Josephus.cursorNode.nextNode;
}while(!Josephus.cursorNode.equals(Josephus.firstNode));
}
/**
*寻找开始数数的节点,为游戏做好准备
*/
private static void prePlay(){
Josephus.cursorNode = Josephus.firstNode;
//寻找开始数数的节点
for(int i = 1;i < Josephus.startNumber;i++){
Josephus.cursorNode = Josephus.cursorNode.nextNode;
}
}
/**
*开始游戏
*/
private static void play(){
//输出游戏最后的剩下那个节点的值
if(Josephus.cursorNode.nextNode.equals(Josephus.cursorNode)){
System.out.println("最后剩下的小孩是:"+Josephus.cursorNode.number);
return;
}
for(int j = 1;j < Josephus.devilNumber;j++){
Josephus.cursorNode = Josephus.cursorNode.nextNode;
}
//数到devilNumber的节点将出列
System.out.println("编号为"+Josephus.cursorNode.number+"的小孩出列!");
Josephus.cursorNode.preNode.nextNode = Josephus.cursorNode.nextNode;
Josephus.cursorNode.nextNode.preNode = Josephus.cursorNode.preNode;
//从下一个节点开始继续游戏
Josephus.cursorNode = Josephus.cursorNode.nextNode;
Josephus.play();
}
}
引自:http://user.qzone.qq.com/864717359/infocenter?ptlang=2052