单向环形链表之约瑟夫问题(JAVA实现)
1、约瑟夫问题介绍:
--------一堆猴子(小孩)都有编号,编号是1,2,3 …m,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第N个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,求出圈的猴子编号。
2、代码思路:
围成一圈,类似环形链表结构。 单向环形链表,即单向链表最后一个节点指向首节点,构成环形。每出圈一个,将其删除。
链表的创建:
(1)先创建第一个节点,给定的first节点=该节点,first节点并指向该节点,辅助节点=first,形成环形。
(2)每创建一个新节点,加入到环形中。(使用辅助节点)。辅助节点.next=新节点,新节点.next=first,辅助节点后移。
链表的遍历:
(1)辅助节点,指向first。
(2)while遍历。终止条件:辅助节点.next=first。
出圈操作:
(1)辅助节点helper放置链表最后。
(2)先定位几号小孩报数。报数M,first和helper移动M-1下
(3)first指向的小孩出圈。first=first.nest;helper.next=first。
3、代码实现:
package test.lianbiao;
/**
* @author shkstart
* @create 2021-01-07 9:39
*/
public class Joepfu {
public static void main(String[] args) {
CorcleSlinkList corcleSlinkList = new CorcleSlinkList();
corcleSlinkList.add(5);
corcleSlinkList.list();
corcleSlinkList.count(1,2,5);
}
}
class CorcleSlinkList {
private Boy first = new Boy(0);//first 节点
public void add(int num) {
//num>1 先判断,此处省略
Boy curboy = null;//辅助变量 因为first不能动
for (int i = 1; i <= num; i++) {
Boy boy = new Boy(i);
if (i == 1) {
first = boy;
first.setNext(boy);//构成环
curboy = first;
}
else{
curboy.setNext(boy);
boy.setNext(first);
curboy = curboy.getNext();
}
}
}
public void list(){
if(first.getNext()==null){
System.out.println("空");return;
}
//first 不能动,辅助变量
Boy curboy=first; //指向变量
while (true){
System.out.printf("小孩编号%d\n",curboy.getNo());
if (curboy.getNext() == first){
break;
}
curboy=curboy.getNext();
}
}
public void count(int startNo,int cnum,int num){ //从第startNo号小孩数,数cnum个数,有几个小孩
if (first.getNext() == null || startNo < 1 || startNo > num) {
System.out.println("参数输入有误, 请重新输入");
return;
}
Boy helper=first;
while (true){ //helper在链表最后
if(helper.getNext()==first){
break;
}
helper=helper.getNext();
}
for (int j=1;j<startNo;j++){
first=first.getNext();
helper=helper.getNext();//定位到第一个数数的人
}
while (first.getNext()!=first) {//直到圈中只有一个人
for (int i =1; i < cnum; i++) {
first = first.getNext();
helper = helper.getNext(); //定位到出圈的人
}
System.out.println(first.getNo());
first = first.getNext();
helper.setNext(first);
}
System.out.println(first.getNo());//最后一人也要输出显示
}
}
class Boy {
private int no;// 编号
private Boy next; // 指向下一个节点,默认null
public Boy(int no) {
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Boy getNext() {
return next;
}
public void setNext(Boy next) {
this.next = next;
}
}
共5人,数到2的人出圈,最后结果为 2 4 1 5 3。
PS:打call尚硅谷!