数据结构与算法之Josephu(约瑟夫环问题)
单向环形链表应用场景
Josephu(约瑟夫环问题)
- 提示:用一个不带头结点的循环链表来处理Josephu问题:先构建一个有n个结点的单循环链表。然后由k结点起从1开始计数。记到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束
- 约瑟夫环问题-创建环形链表的思路图解
- 约瑟夫环问题-小孩出圈的思路分析图
- 约瑟夫环问题-创建环形链表的思路图解
- 代码实现
public class Josephu {public static void main(String[] args) {// 测试一把看看构建环形链表,和遍历是否okCircleSingleList circleSingleList = new CircleSingleList();circleSingleList.addBoy(5);circleSingleList.display();circleSingleList.countBoy(1,2);}}
class CircleSingleList {private Boy first;/*** 构建一个循环单向链表* @param n*/public void addBoy(int n) {if(n <= 0) {System.out.println("您输入的数字不合法");return;}Boy cur = null;for(int i = 1; i <= n;i++) {Boy boy = new Boy(i);if(first == null) {first = boy;cur = first;boy.setNext(boy);}else {boy.setNext(first);cur.setNext(boy);cur = boy;}}}/*** 显示链表*/public void display() {if(first == null) {System.out.println("没有任何小孩");return;}Boy cur = first;do {System.out.printf("编号为%d的小孩\n",cur.getNo());cur = cur.getNext();}while(cur != first);}/*** 获取循环链表个数* @return*/public int size() {Boy cur = first;int count = 0;if(cur == null) {return 0;}do{count++;cur = cur.getNext();}while(cur != first);return count;}/*** 形成一个出队序列* @param k* @param m*/public void countBoy(int k,int m) {int size = size();if(size == 0 || k <= 0 || k > size) {System.out.println("参数有误");return;}// 找到最后一个结点Boy pre = first;Boy cur = first;while(pre.getNext() != first) {pre = pre.getNext();}// 先找到第k个结点for(int i = 1; i < k;i++) {cur = cur.getNext();pre = pre.getNext();}// 移动m-1while(pre != cur) {for(int i = 1; i < m;i++) {cur = cur.getNext();pre = pre.getNext();}System.out.printf("编号为%d的小孩出队\n",cur.getNo());// 删除第m个结点cur = cur.getNext();pre.setNext(cur);}System.out.printf("编号为%d的小孩出队\n",cur.getNo());}
}
class Boy {private int no;private Boy next;public Boy() {}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;}
}