- 实现图解
- 代码实现
出圈的实现思路:
代码实现:
package com.demo;
public class JosePhu {
public static void main(String[] args) {
//测试看看创建和遍历环形链表是否正确
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addBoy( 5 );//加入5个小孩
circleSingleLinkedList.showBoy();
//出圈顺序
circleSingleLinkedList.countBoy( 1, 2, 5 );
}
}
//创建一个Boy类 表示一个节点
class Boy {
private int no;//编号
private Boy next;//指向下一个节点,默认null
public Boy(int no) {
this.no = no;
}
public void setNo(int no) {
this.no = no;
}
public void setNext(Boy next) {
this.next = next;
}
public int getNo() {
return no;
}
public Boy getNext() {
return next;
}
}
//创建一个环形的单向链表
class CircleSingleLinkedList {
//创建一个first节点,当前没有编号
private Boy first = null;
//添加小孩节点,构建一个环形的链表
public void addBoy(int nums) {
if (nums < 1) {
System.out.println( "nums的值不正确" );
return;//结束
}
Boy curBoy = null; //辅助指针,first不能动需要一个辅助指针
//使用for循环,创建环形链表
for (int i = 1; i <= nums; i++) {
//根据编号,创建小孩节点
Boy boy = new Boy( i );
if (i == 1) {
first = boy;
first.setNext( first );//创建了环形链表
curBoy = first;//指向第一个小孩
} else {
curBoy.setNext( boy );//使循环的那条线指向下一个节点
boy.setNext( first );//构建了循环线
curBoy = boy;//curBoy总是指向最后一个节点
}
}
}
// 写下一个方法遍历当前的环形链表
public void showBoy() {
//判断链表是否为空
if (first == null) {
System.out.println( "没有孩子节点,链表为空" );
return;//终止
}
//因为first不能动,所以需要辅助指针
Boy curBoy = first;
while (true) {
System.out.printf( "小孩的编号%d\n", curBoy.getNo() );
if (curBoy.getNext() == first) {
//说明遍历完毕
break;//退出
}
curBoy = curBoy.getNext();//继续下一个
}
}
//根据用户的输入,计算出小孩出圈的方法
/*
* @param startNo 表示从第几个小孩开始数数
* @param countNum 表示数几下
* @param nums 表示总共多少个小孩
* */
public void countBoy(int startNo, int countNum, int nums) {
//对输入的数据进行校验
if (first == null || startNo < 1 || startNo > nums) {
System.out.println( "输入的数据有误,please input again" );
return;//终止
}
//创建辅助指针完成小孩出圈,而且辅助指针指向最后一个节点
Boy helper = first;
while (true) {
if (helper.getNext() == first) {
//说明helper指向最后的小孩节点
break;
}
helper = helper.getNext();
}
// 小孩报数前先让frist和helper移动k-1次(k代表小孩报数的位置)
for (int i = 0; i < startNo - 1; i++) {
first = first.getNext();
helper = helper.getNext();
}
//当小孩报数时first和helper先移动m-1次,然后出圈
//这是一个循环的操作,直到圈中只有一个节点
while (true) {
if (helper == first) {
//只有一个节点
break;
}
//first和helper先移动m-1次,然后出圈
for (int i = 0; i < countNum - 1; i++) {
first = first.getNext();
helper = helper.getNext();
}
//这时first指向的就是要出圈的小孩节点
System.out.printf( "出圈小孩节点%d\n", first.getNo() );
//让小孩节点出圈操作
first = first.getNext();
helper.setNext( first );//这两步使出圈的节点消失
}
System.out.printf( "最后圈中的节点%d\n", first.getNo() );
}
}
成功后: