package linkedlist;
/*
* 约瑟夫环游戏:
* 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,
* 数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,
* 依次类推,直到只剩下最后一个人为止.
* 这里可以使用单向循环链表来解决这个问题
*/
public class JosepfuGame
{
public people first=null;
/*
* 创建拥有这么多人的环形链表
*/
public void creat(int number)
{
//先对number的值进行校验
if(number<2)
{
System.out.println("环形链表的大小必须大于1");
return;
}
//这个temp就是跟踪每一次添加的people,所以temp就是链表的最后一个节点
people temp=null;
for (int i = 1; i <= number; i++)
{
people index=new people(i);
//如果是第一个要特殊处理,这里是将第一个赋值给first
if(i==1)
{
first=index;
first.next=first;
temp=index;
}
else
{
temp.next=index;
index.next=first;
temp=index;
}
}
}
/**
* 进行约瑟夫环游戏
* @param number 玩这个游戏的有多少个人
* @param begin 从哪一个人开始数数
* @param count 数到第几的人就要出去
* 思路:因为这时单向链表,如果想删除当前节点,
* 就必须找到它的前一个节点,这样子才能删除
* 所以我们就用一个辅助temp指向要删除节点的前一个
*/
public void Game(int number,int begin,int count)
{
//先进行数据校验校对
if(first==null||begin<1||begin>number)
{
System.out.println("there is error");
return;
}
people temp=first;
while(temp.next!=first)
{
temp=temp.next;
}
//这里移动begin-1次就行了,因为第一个first已经算了
for(int i=0;i<begin-1;i++)
{
temp=temp.next;
first=first.next;
}
//然后就一直数
while(true)
{
if(temp==first)
{
break;
}
for(int j=0;j<count-1;j++)
{
temp=temp.next;
first=first.next;
}
//然后就删除这个节点,这个节点是first
System.out.println(first+"你死了");
first=first.next;
temp.next=first;
}
System.out.println("最后的人"+first);
}
/*
* 遍历当前环形链表
*/
public void show()
{
//如果这个链表本来是空的,没有这个判断,下面会有空指针异常
if(first==null)
{
System.out.println("no people");
return;
}
people temp=first;
while(true)
{
System.out.println(temp);
if(temp.next==first)
break;
temp=temp.next;
}
}
public static void main(String[] args)
{
JosepfuGame game=new JosepfuGame();
game.creat(150);
game.show();
game.Game(150, 110, 21);
}
}
class people
{
public int number;
public people next;
public people(int number)
{
this.number = number;
}
@Override
public String toString()
{
return "people [number=" + number + "]";
}
}
单向循环链表的创建,增加,删除(以约瑟夫环游戏为例)
猜你喜欢
转载自blog.csdn.net/qq_43416157/article/details/104303277
今日推荐
周排行