单向循环链表解决约瑟夫问题
什么是单向循环链表
单向循环链表基本与单向链表相同,唯一的区别就是单向循环链表的尾节点指向的不是null,而是头节点(注意:不是头指针).
因此,单向循环链表的任何节点的下一部分都不存在NULL值。
由于单向循环链表的特性,它在处理一些环状数据的时候十分有效.大名鼎鼎的约瑟夫环问题就可以用循环单向链表求解,下面我们会有进一步的介绍。
由于单向循环链表和单向链表的差别真的不大,增添改查原理都相同。因此在这里我们不详细讲解,只提供源码。(如果你还是不理解的话,这里有单向链表的传送门)
什么是约瑟夫环问题
大家知道什么是约瑟夫环吗?
各位读者是不是心里想着:“知道谁还看你在这废话。”然后悄悄地攥紧了拳头?别,各位大哥大姐千万别激动,给小弟点时间,让小弟为你排忧解难。
约瑟夫问题为:设编号为1,2,……n得n个人围坐一圈,约定编号为k(k大于等于1并且小于等于n)的人从1开始报数,数到m的那个人出列。它的下一位继续从1开始报数,数到m的人出列,依次类推,直到所有人都出列为止。
这就是著名的“约瑟夫环”问题,是不是还挺有趣的感觉(有趣个鬼不为了面试、加薪谁搞这东西)。
代码演示
结点类
package com.ma.linked;
//结点类
public class Boy {
//结点编号
private int no;
//指向下一个结点
private Boy next;
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;
}
}
package com.ma.linked;
public class CircleSingleLinkedTest {
private Boy first = new Boy(-1);
//构建环形链表
public void addBoy(int num){
if (num < 1){
System.out.println("数据不正常");
return;
}
Boy temp = first;
for (int i = 1; i <= num; i++) {
Boy boy = new Boy(i);
//判断你是否是第一个小孩
if (i == 1){
first = boy;
first.setNext(first);
temp = first;
}else {
temp.setNext(boy);
boy.setNext(first);
temp = boy;
}
}
}
//查看链表中的结点
public void showBoy(){
if (first == null){
System.out.println("该链表为空");
return;
}
Boy boy = first;
while (true){
System.out.println("孩子的编号为"+boy.getNo());
if (boy.getNext() == first){
break;
}
boy = boy.getNext();
}
}
//当调用该方法,输入第几个小孩子开始数数,输几次,环形链表中总共几个孩子
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.getNext() == first){
break;
}
helper = helper.getNext();
}
//寻找初始位置,把first定义为起始位置
for (int i = 0; i < startNo-1; i++) {
first = first.getNext();
helper = helper.getNext();
}
//当小孩报数时,数到m的孩子出列,让first和helper移动m-1次即可,找到了已出列的孩子
while (true){
if (first == helper){break;}
for (int i = 0; i < countNum-1; i++) {
first = first.getNext();
helper = helper.getNext();
}
System.out.println("编号"+first.getNo()+"的孩子出列");
first = first.getNext();
helper.setNext(first);
}
System.out.println("编号为"+first.getNo()+"的孩子最后出列");
}
}
测试代码
package com.ma.linked;
public class LinkedTest3 {
public static void main(String[] args) {
CircleSingleLinkedTest circleSingleLinkedTest = new CircleSingleLinkedTest();
circleSingleLinkedTest.addBoy(5);
circleSingleLinkedTest.showBoy();
circleSingleLinkedTest.countBoy(1,2,5);
}
}
kedTest();
circleSingleLinkedTest.addBoy(5);
circleSingleLinkedTest.showBoy();
circleSingleLinkedTest.countBoy(1,2,5);
}
}