问题:
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列
思路:
利用单项链表循环遍历,直至人数不够继续游戏时停止。
public class josepfuTest {
public static void main(String[] args) {
new PersonList().Josefu(41,1,3);
}
}
//定义一个类,用来创建单向环形链表
class Person{
int val;
Person next;
Person(int val){
this.val=val;
}
}
class PersonList{
Person head =new Person(0);
PersonList(){
}
//添加人
public void add(int a){
if(a<1){
return;
}
Person temp=head;
for(int i=1;i<=a;i++){
Person person=new Person(i);
if(a==1){
temp.next=person;
person.next=temp;
}else {
temp.next=person;
person.next=head;
temp=temp.next;
}
}
}
//输出所有人以及编号,且不计算头节点
public void showPerson(){
Person temp=head;
if(temp.next==null){
System.out.println("空链表");
return;
}
while (temp.next!=head){
System.out.println("这是第"+temp.next.val+"个人");
temp=temp.next;
}
}
//获取人数,且不计算头节点
public int getcount(){
Person temp=head;
int count=0;
while (temp.next!=head){
count++;
temp=temp.next;
}
return count;
}
//处理约瑟夫问题核心代码
public void josepfu(int start,int out){
//去掉链表中的头节点head
Person temp1=head;
Person temp2=head.next;
int nums=this.getcount();
while (temp1.next!=head){
temp1=temp1.next;
}
temp1.next=temp2;//第一个人为temp2
Person temp3=temp1;
int count=0;//遍历时计数,如果等于start,则开始进行游戏
boolean flag=true;//
while (flag){
count++;
if(count==start){
int count1=1;
int count2=0;
while (true){
if(count1%out==0){
System.out.println("编号"+temp3.next.val+"的人出局");
temp3.next=temp3.next.next;
count1++;
count2++;
}
//如果剩下的人不足以报数至out值,则停止游戏
else if((nums-count2)<out){
System.out.println(count2);
break;
} else {
count1++;
temp3=temp3.next;
}
}
flag=false;
}else {
temp3=temp3.next;
}
}
}
//处理约瑟夫问题的方法,count是总人数,start是开始位置,out报数至out时出局
public void Josefu(int count,int start,int out){
this.add(count);
this.josepfu(start,out);
}
}