您的位置:首页 > 编程语言 > Java开发

Java实现约瑟夫问题

2017-03-31 09:32 453 查看
约瑟夫问题

概述:

一共有n个人围成一圈,事先给定两个值k,m,其中k代表一开始从第k个人开始数1,m代表数到m的人出圈,每次出圈一个人,从出圈的那个人的下一个人继续从1开始数,数到m的人再出圈,如此循环,直到最后一个人留在圈里,这样我们就可以得到一个按出圈顺序排列的数的序列。

根据这样的问题,我们利用java来编程实现:

主要思想:

1、创建一个小孩类,其拥有自身的元素值,又能够指向下一个小孩

2、创建一个环形链表代表一个圈,每次出圈一个小孩,就将其上一个小孩的nextchild指向其下一个小孩,这样就相当于出圈了,即从环形链表中删除

3、出圈的动作是一直进行的,直到剩下最后一个小孩,我们需要设置环形链表的长度len,即开始游戏之前一共有多少个小孩参加游戏,每次出圈len减一

/**
* Author:MrBread
* Function:解决约瑟夫问题
* Date:2017-03-29
*/
package com.mycode.test;

public class Joseph {
public static void main(String []args){
CycleLink cl=new CycleLink();  //创建环形链表对象
cl.setLen(10);  //设置环形链表的长度
cl.create();   //初始化环形链表
cl.setK(2);    //设置k
cl.setM(2);    //设置m
cl.play();     //开始游戏
}
}

//定义一个小孩类
class Child{
int num;
Child nextchild;

//构造函数设置小孩中的num值
public Child(int num){
this.num=num;
}

public Child(){}
}

//定义一个环形链表
class CycleLink{
Child firstchild;//定义环形链表的头节点
Child temp;
int k=0;  //k代表从第几个小孩开始数
int m=0;  //m代表数到几就出圈
int len=0; //代表环形链表中小孩的总数

//设置环形链表的长度
public void setLen(int len){
this.len=len;
}
//构造设置k值的方法
public void setK(int k){
this.k=k;
}

//构造设置m值的方法
public void setM(int m){
this.m=m;
}

//初始化环形链表,即根据len大小创建具体的小孩
public void create(){
for(int i=1;i<=len;i++){
if(i==1){
Child ch=new Child(i);
temp=ch;
firstchild=ch;
}else if(i>1&&i<len){
Child ch=new Child(i);
temp.nextchild=ch;
temp=temp.nextchild;
}else{
Child ch=new Child(i);
temp.nextchild=ch;
temp=temp.nextchild;
temp.nextchild=firstchild;
}
}
}

//开始丢手帕游戏,最后按出圈的顺序输出一串数
public void play(){

//遍历环形链表找出第k个人
temp=firstchild;
for(int i=1;i<k;i++){
temp=temp.nextchild;
}
//跳出循环之后就知道temp指向了开始报数的那个小孩

while(this.len!=1)  //一直循环,直到剩下最后一个小孩
{
//从temp指向的那个小孩开始报1,遍历链表找到数m的那个小孩
for(int j=1;j<m;j++)
{
temp=temp.nextchild;
}
//循环结束之后我们就知道temp指向了要出圈的那个小孩

//打印要出圈小孩的num值
System.out.println(temp.num);

//将那个要出圈的小孩请出圈,即删除该小孩
Child temp2=new Child();
temp2=firstchild;
for(int i=1;i<=len;i++){
if(temp2.nextchild==temp){  //若temp2指向的是要删除小孩的上一个小孩,则跳出循环
break;
}
temp2=temp2.nextchild;
}
temp2.nextchild=temp.nextchild;//完成删除操作

4000
//让下一个小孩重新从1开始报数
temp=temp.nextchild;
this.len--;//每次请出圈就把链表长度减一
}
//打印最后一个小孩的num值
System.out.println(temp.num);
}
}


测试结果如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 约瑟夫问题