Josephu 问题 Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
提示 用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。
public class Josepfu {
public static void main(String[] args) {
//测试环形链表
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addBoy(5);
circleSingleLinkedList.display();
circleSingleLinkedList.countBoy(1,2,5);
}
}
//创建环形单向链表
class CircleSingleLinkedList{
//创建first节点
private Boy first=new Boy(-1);
//添加小孩节点,构建成一个环形链表
public void addBoy(int nums){
if(nums<1){
System.out.println("nums值不能小于1");
return;
}
Boy curBoy=null; //临时存放小孩
for (int i = 1; i <= nums; i++) {
//根据编号创建环形链表
Boy boy = new Boy(i);
if(i==1){
first=boy;
first.next=first;//构成环装
curBoy=first;//让curBoy指向第一个小孩
}else {
curBoy.next=boy;
boy.next=first;
curBoy=boy;
}
}
}
//遍历环形链表
public void display(){
//判断链表是否为空
if(first==null){
System.out.println("没有任何小孩~");
return ;
}
//first不能动 使用辅助指针完成遍历
Boy curBoy=first;
while (true){
System.out.println("小孩的编号 "+curBoy.getNo());
if(curBoy.next==first){
//遍历完毕
break;
}
curBoy=curBoy.next;//后移
}
}
/**
*
* @param startNo 从第几个小孩开始数数
* @param countNum 表示数几下
* @param nums 共有最初有多少小孩在圈中
*/
//根据用户输入计算小孩出圈的顺序
public void countBoy(int startNo,int countNum,int nums){
//数据校验
if(first==null||startNo<1||startNo>nums){
System.out.println("参数输入有误");
return ;
}
//创建辅助指针 事先指向最后一个节点
Boy helper=first;
while (true){
if(helper.next==first){
break;//说明已经指向了最后小孩节点
}
helper=helper.next;
}
//小孩报数前 first和helper移动k-1次
for (int j=0;j<startNo-1;j++){
first=first.next;
helper=helper.next;
}
//小孩报数时,first和helper指针同时移动countNum-1次,然后出圈
//循环操作直到圈中只有一个
while (true){
if (helper==first){
break;//圈中只有一个小孩
}
//移动countNum-1
for (int j = 0; j < countNum-1; j++) {
first=first.next;
helper=helper.next;
}
//此时firster指向节点 就是出圈的小孩节点
System.out.println("小孩出圈: "+first.getNo());
//将first指向的节点小孩出圈
first=first.next;
helper.next=first;
}
System.out.println("最后留在圈中小孩:"+first.getNo());
}
}
//节点
class Boy{
private int no;
public Boy next;
public Boy(int no){
this.no=no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
}