链表引用——约瑟夫问题
约瑟夫问题
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;//指向下一个节点;默认 null public 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; } }