看了约瑟夫环的问题,借鉴的别人的方式创建的环形单链表,加上了我自己理解的注释(不知道对不对,错了指正一下),后面的约瑟夫出列的问题看不下去(理解不了那个思路),于是自己写了一个:
首先是节点类:
/**
* boy结点
* @author zzt
*
*/
class Boy {
private int no;
private Boy next;
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;
}
public Boy(int no) {
super();
this.no = no;
}
@Override
public String toString() {
return "Boy [no=" + no +"]";
}
}
然后是创建环形链表:
class CircleSingleLinkedList {
//创建一个first空结点,当前无编号
//first的作用是指向第一个节点,类似于头结点,但是无编号
private Boy first = null;
/**
* 添加boy 结点,构建一个环形链表
* nums是boy的数量
* @param nums
*/
public void addBoyNode(int nums) {
//nums必须大于1
if(nums<1) {
System.out.println("nums的值必须大于1");
return;
}
//辅助指针
Boy temp = null;
for (int i=1;i<=nums;i++) {
//循环创建新的结点
Boy boy = new Boy(i);
//第一个boy
if(i==1) {
//先创建第一个节点,让first指向该节点,并形成环状
//只有一个节点,要自己指自己
first = boy;
first.setNext(first);//将1的值给自己,然后自己指自己,first成了头结点
temp = first; //后移
System.out.println("first:" + first);
}else {
temp.setNext(boy);//temp=first,temp改变,first也会改变
//next是一个对象,setNext改变,是改变了对象本身
//这一步的目的是将boy的上一个结点的next指向boy
boy.setNext(first);//指向头结点
temp = boy;
System.out.println("boy"+ i+":" + boy);
}
}
}
/**
*
* 遍历链表
*/
public void showBoy() {
//判断链表是否为空
//first指向第一个结点,first也=第一个节点
if(first==null) {
System.out.println("没有任何boy");
return;
}
//因为first不能动,仍然使用一个临时结点temp
Boy temp = first;
//循环
while(true) {
System.out.printf("boy的编号 %d\n",temp.getNo());
//temp.getNext()==first,说明已经是最后一个结点
if(temp.getNext()==first) {
//遍历到最后
break;
}
temp=temp.getNext();//temp后移
}
}
/**
* 根据输入,计算约瑟夫环的出列顺序
* @param k 从第k个人开始数1 (1 <= k <= nums)
* @param m 数到m
* @param nums 总共有nums个人
*/
public void JosephusOut(int k, int m, int nums) {
addBoyNode(nums);
//数据检验
if(first==null||nums<1||k<1||k>nums) {
System.out.println("数据有误,重新输入");
return;
}
//找到第k结点前面的一个结点,first就是第一个结点
Boy temp = first;
while(true) {
if(temp.getNo()==k-1) {
//找到第k-1个结点
break;
}
if(k==1) {
if(temp.getNo()==nums) {
//找到第k-1个结点
break;
}
}
// System.out.println(k);
// System.out.println("NO"+temp.getNo());
temp = temp.getNext();
}
//遍历到最后一个
while(true) {
//当只剩一个人时,会自己指自己,遍历结束
if(temp.getNext()==temp) {
break;
}
//从第k个人开始数1,数到m出列,找到数m的前一个人
for(int i=1;i<m;i++) {
temp= temp.getNext();
}
System.out.println("第"+temp.getNext().getNo()+"号 boy出列");
temp.setNext(temp.getNext().getNext());
}
System.out.println("第"+temp.getNext().getNo()+"号 boy出列");
}
}