约瑟夫环
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
该问题亦称为丢手绢游戏,以下用丢手绢游戏的概念来注释。
用顺序表实现约瑟夫环:
public class linkDemo
{
public static void main(String[] args) {
Link link=new Link();
link.setLen(10);
link.createLink();
link.setStart(2);
link.setDistance(3);
//link.Print();
link.play();
}
}
class Link{
//先定义一个指向链表第一个小孩的引用
int len=0; //表示共有几个小孩
int start=0;
int distance=0;
int index=0;
Child[] arr;
public void setLen (int len)
{
this.len=len;
}
public void setStart(int start)
{
this.start=start;
}
public void setDistance(int distance)
{
this.distance=distance;
}
//开始play
public void play()
{
index=start-1;
while(this.len!=1)
{
//2.数m下
index=(index+distance-1)%len;
//System.out.println("index:"+index);
System.out.println(Delete(index).no);
}
//输出最后一个小孩
System.out.println(arr[index].no);
}
public void createLink()
{
arr=new Child[len];
for(int i=0;i<len;i++)
{
arr[i]=new Child(i+1);
}
}
public Child Delete(int i)
{
if (len == 0)
throw new RuntimeException( "下溢");
Child x = arr[i];
for (int j = i; j < len-1; j++)
arr[j] = arr[j+1];
len--;
return x;
}
public void Print()
{
for(int i=0;i<len;i++)
{
System.out.print(arr[i].no+" ");
}
}
}
class Child
{
int no;
public Child(int no)
{
//给一个编号
this.no=no;
}
}
用链表实现约瑟夫环:
public class Demo1
{
public static void main(String[] args) {
CycLink cyclink=new CycLink();
cyclink.setLen(10);
cyclink.createLink();
cyclink.setStart(2);
cyclink.setDistance(3);
// cyclink.show();
cyclink.play();
}
}
class CycLink{
//先定义一个指向链表第一个小孩的引用
Child firstChild=null;
Child temp=null;
int len=0; //表示共有几个小孩
int start=0;
int distance=0;
public void setLen (int len)
{
this.len=len;
}
public void setStart(int start)
{
this.start=start;
}
public void setDistance(int distance)
{
this.distance=distance;
}
//开始play
public void play()
{
Child temp=this.firstChild;
//1.先找到开始报数的人
for(int i=1;i<start;i++)
{
temp=temp.nextChild;
}
while(this.len!=1)
{
//2.数m下
//找到要出圈的前一个小孩
for(int j=1;j<distance-1;j++)
{
temp=temp.nextChild;
}
System.out.println(temp.nextChild.no);
//3.将数到m的小孩,退出圈。
temp.nextChild=temp.nextChild.nextChild;
//让temp指向下一个小孩
temp=temp.nextChild;
this.len--;
}
//输出最后一个小孩
System.out.println(temp.no);
}
public void createLink()
{
for(int i=1;i<=len;i++)
{
//创建第一个小孩
if(i==1){
Child ch=new Child(i);
this.firstChild=ch;
this.temp=ch;
}
else
{
//创建最后一个小孩
if(i==len){
Child ch=new Child(i);
temp.nextChild=ch;
temp=ch;
temp.nextChild=this.firstChild;
}
//继续创建小孩
else
{
Child ch=new Child(i);
temp.nextChild=ch;
temp=ch;
}
}
}
}
public void show()
{
//定义工作指针
Child temp=this.firstChild;
do{
System.out.println(temp.no);
temp=temp.nextChild;
}while(temp!=this.firstChild);
}
}
class Child
{
int no;
Child nextChild=null;
public Child(int no)
{
//编号
this.no=no;
}
}
实验总结和个人想法:
该实验的链表形式代码,参考韩顺平视频中的代码,但在链表的基础上,自行将其改写为顺序表形式代码。通过本实验,我进一步理解到指针在线性表中发挥的作用。