public class Test_CircleList {
public static void main(String[] args) {
CircleList c = new CircleList();
c.addBoy(5);
c.list();
c.popBoy(1,2,5);
}
}
class Boy{
private int id;
private Boy next;
public Boy(){}
public Boy(int id){
this.id = id;
}
public void setNext(Boy next) {
this.next = next;
}
public Boy getNext() {
return next;
}
@Override
public String toString() {
return "Boy{"+"id="+id +'}';
}
}
class CircleList{
private Boy first = new Boy();
/**
* @param nums 小孩数量
*/
public void addBoy(int nums){
Boy temp = new Boy();
if(nums<1){
System.out.println("无意义!");
}else{
while(true){
for(int i =1;i<=nums;i++){
Boy note = new Boy(i);
// 注意:这里头节点(first)不为空 环形数组是要空出一个变量 这里不需要
if(i == 1){
first = note;
note.setNext(first); // next指向调整为指向头元素
temp = first;
}else{
temp.setNext(note);
temp = note;
note.setNext(first); // next指向调整为指向头元素
}
}
break;
}
}
}
public void list(){
Boy temp = first;
while(true){
System.out.println(temp);
if(temp.getNext() == first){
break;
}else{
temp = temp.getNext();
}
}
}
/**
*
* @param startno 指定的第一个小孩的位置
* @param countNum 要传递的次数
* @param nums 小孩的总人数
*/
public void popBoy(int startno,int countNum,int nums){
//先判断有没有执行的必要
if(startno<1||startno>nums||first==null){
System.out.println("出错了");
return;
}
//辅助节点很重要,因为是单链表,所以需要使用一个辅助接点就对接前一个元素
Boy temp = first;
//将辅助节点进行遍历,对接到first元素的前一个元素
for(int i =0;i<nums;i++){
if(temp.getNext()==first){
break;
}else{
temp = temp.getNext();
}
}
//将两个节点移动到指定的开始小孩的元素上
//first在指定的元素上 temp在他的前一个元素上 这里的重点是执行n-1次
for(int i =0;i<startno-1;i++){
first = first.getNext();
temp = temp.getNext();
}
//如果temp和first指向同一个元素,那么就代表只剩下最后一个环形链表元素
while(true){
if(temp == first){
break;
}
//这里同样是只移动N-1次
for(int j=0;j<countNum-1;j++){
first = first.getNext();
temp = temp.getNext();
}
System.out.println("出圈的小孩编号为:"+first);
//将出圈小孩删除的操作
//就是将temp(也就是first的前一个元素)的next域指向出圈小孩的下一个小孩
first = first.getNext();
temp.setNext(first);
}
System.out.println("最后一个小孩编号为:"+first);
}
}