约瑟夫问题
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) {CircleSingleLinkeList c = new CircleSingleLinkeList();c.addNode(5);c.show();c.roundBoy(1,2,5);} }/****/ class CircleSingleLinkeList {//创建 first 节点private Boy first = new Boy(-1);/*** 构建环形链表** @param num*/public void addNode(int num) {if (num < 1) {System.out.println("输入错误");return;} else {Boy curBoy = null;for (int i = 1; i <= num; i++) {//根据编号,创建节点Boy boy = new Boy(i);//第一个boy 特殊处理if (i == 1) {first = boy;first.setNext(first); //构成环形curBoy = first;} else {curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}}/*** 遍历环形链表*/public void show() {if (first == null) {System.out.println("空空");return;} else {Boy curBoy = first;while (true) {System.out.println("编号- " + curBoy.getId());if (curBoy.getNext() == first) {//遍历完成break;} else {//curBoy 后移curBoy = curBoy.getNext();}}}}/*** Josepfu 出队顺序** @param starId 表示从第几个Boy开始* @param countNum 步长* @param total 总数*/public void roundBoy(int starId, int countNum, int total) {//前置判断if (first == null || starId < 1 || starId > total) {System.out.println("参数有误");} else {//创建辅助节点Boy helper = first;while (true) {if (helper.getNext() == first) {//helper 此时是最后一个节点break;} else {//helper 后移helper = helper.getNext();}}//报数前,先让 first & helper 移动 k - 1 次for (int i = 0; i < starId - 1; i++) {first = first.getNext();helper = helper.getNext();}//当小孩报数时,让 first & helper 同时移动 m -1次,然后出圈//这里是一个循环操作,直到只剩一个节点while (true) {if (helper == first) {//只有一个节点break;} else {for (int i = 0; i < countNum - 1; i++) {first = first.getNext();helper = helper.getNext();}//此时 first 指向的节点,即将出圈System.out.println(first.getId() + " 将出圈");//更改指向,使其出圈first = first.getNext();helper.setNext(first);}System.out.println("圈中还有 " + helper.getId());}}}}/*** 小孩类*/ class Boy {private int id;private Boy next;//指向下一个节点;默认 nullpublic int getId() {return id;}public void setId(int id) {this.id = id;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}public Boy(int id) {this.id = id;} }