1.单向环形链表介绍:单向环形链表就是单向链表的各个节点的指向形成一个环形,当链表由一个节点时,它的next指向自己,两个或两个以上则是最后一个的next指向第一个。
2.约瑟夫问题的介绍:设编号为12....n的n个人围坐一圈,约定编号为k(1<k<n)的人开始报数,数到m的那个人出列,它的下一位右从1开始报数,数到m的那个人出列,依此类推,直到所有人出队为止,由此产生一个出队编号的序列。
3.用单向环形链表解决约瑟夫问题的思路:
构建环形链表
① 先创建第一个节点,由first节点指向该节点,并形成环形。
②后面当我们每创建一个新的节点,就把该节点,加入到已有的环形链表即可。
遍历环形链表
①先让一个辅助指针(变量)curboy指向,指向first节点。
②然后通过while循环遍历该环形链表即可,curboy.next==first结束。
小孩出圈
① 需要创建一个辅助指针helper,事先应该指向链表的最后一个节点。
②小孩报数前,先让first指针和helper指针移动k-1次。
③当小孩报数报数,first和helper指针同时移动m-1次,这时让first指向的小孩出圈即可fist=first.next,helper.next=first.
4.代码实现:
public class Josepfu {
public static void main(String[] args) {
CircleList circleList = new CircleList();
circleList.addList(5);
circleList.showBoy();
circleList.outBoy(1,2,5);
}
}
// 构建单向环形链表
class CircleList{
// 创建第一个first节点,没有编号。
private Boy first=null;
// 添加节点,构建环形单向链表
public void addList(int num){
if(num<1){
System.out.println("num数值不正确!!!");
return;
}
Boy curBoy=null;// 辅助指针
for(int i=1;i<=num;i++){
Boy boy = new Boy(i);
if(i==1){
first=boy;
boy.setNext(first); // 构成环
curBoy=boy;
}else{
curBoy.setNext(boy);
boy.setNext(first);
curBoy=boy;
}
}
}
// 遍历当前环形链表
public void showBoy(){
if(first==null){
System.out.println("环形链表为空~~~~");
}
Boy curBoy=first;
while (curBoy!=null){
System.out.printf("小孩编号 %d\n",curBoy.getNo());
curBoy=curBoy.getNext();
if(curBoy==first){
break;
}
}
}
/**
*
* @param start 从那个小孩开始数
* @param countNum 数多少个数
* @param sum 一一共有多少人
*/
// 根据输入,计算出圈顺序
public void outBoy(int start,int countNum,int sum){
if(first==null||start<1||start>sum){
System.out.println("请输入正确的数");
return;
}
// 辅助指针helper
Boy helper=first;
while(true) {
if (helper.getNext() == first) {
break;
}
helper = helper.getNext();
}
// 小孩报数前,先让first和helper指针移动start-1
for(int i=0;i<start-1;i++){
first=first.getNext();
helper=helper.getNext();
}
// 当小孩报数前先让first和helper移动countNum-1再出圈。
while(true){
if(helper==first){
break;
}
// 让first和helper移动countNum-1
for(int j=0;j<countNum-1;j++){
first=first.getNext();
helper=helper.getNext();
}
// 小孩出圈
System.out.printf("小孩%d出圈\n",first.getNo());
first=first.getNext();
helper.setNext(first);
}
System.out.printf("最后留在圈中的编号%d\n",first.getNo());
}
}
// 创建一个Boy类表示一个节点
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;
}
}