/*
设编号为1,2,3...n,的n个人围坐一圈,约定编号为k(1<k<n),
的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的人又出列,
以此类推,直到所有人出列为止,由此产生一个出队编号的序列
提示:用一个头节点的循环链表来处理这个问题,先构成一个有n个节点的单循环链表,然后
由k节点起从1开始计数,计到m时,对应节点从链表中删除,然后再从被删除节点的下一个节点
又从1开始计数,直到最后一个结点从链表中删除,算法结束
解决约瑟夫问题,用链表
即丢手帕问题*/
public class Demo5
{
public static void main(String[] args)
{
CycLink a= new CycLink();
a.setLen(15);
a.setK(2);
a.setM(4);
a.createLink();
a.show();
a.play();
}
}
class Child
{
int num;
Child nextChild=null;
public Child(){}
public Child(int num)
{
this.num = num;//给一个编号
}
}
/*环形链表*/
class CycLink
{//先定义一个指向链表头节点的引用
Child firChild = new Child();
Child temp = new Child();
int len =0 ;//有多少个小孩
int k = 0 ;//设置从哪一个开始
int m = 0;//设置数多少下
//设置从那一个人开始数数
public void setK(int k ){
this.k = k;
}
//设置数多少下
public void setM(int m){
this.m = m;
}
//play
public void play(){
Child temp = this.firChild;
//1,先找到开始数数的人
for(int i = 0;i<k;i++){
temp = temp.nextChild;
}
//2,数m下
while(this.len != 1){
for(int j = 0;j<m;j++){
temp = temp.nextChild;
}
//找到要出圈的前一个小孩
Child temp2 = temp;
while(temp2.nextChild !=temp){
temp2 = temp2.nextChild;
}
//3,将数到m的小孩,推出去
temp2.nextChild = temp.nextChild;
temp = temp.nextChild;
this.len--;
}
System.out.println("最后出圈的人"+temp.num);
}
public void setLen(int len)//设置链表的长度
{
this.len = len;
}
//初始化环形链表
public void createLink()
{
for(int i = 0;i<=len;i++)
{ if(i == 1)
{
//创建第一个小孩
Child ch = new Child(i);
this.firChild = ch;
this.temp = ch;
}else {
if(i ==len){//最后一个小孩指向第一个小孩
Child lastChild = new Child(i);
temp.nextChild = lastChild;
temp = lastChild;
temp.nextChild = this.firChild;
}else{
//继续创建小孩
Child a = new Child(i);
temp.nextChild = a;
temp = a ;
}
}
}
}
//打印环形链表
public void show()
{
Child temp = firChild;
for(int i = 0;i<len;i++)
{
System.out.print(temp.num+"\t");
temp=temp.nextChild;
}
}
}
约瑟夫问题,用java单链表解决
最新推荐文章于 2022-10-04 12:02:20 发布