使用知识,单向环形链表
public class Josepfu {
public static void main(String[] args) {
// 测试
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addBoy(5);
circleSingleLinkedList.showBoy();
// 测试小孩出圈
circleSingleLinkedList.countBoy(1,2,5);
}
}
// 创建一个环形的单向链表
class CircleSingleLinkedList{
// 创建一个fist节点,当前没有编号
private Boy first = new Boy(-1);
// 添加小孩节点 构建成为一个环形链表
public void addBoy(int nums){
if(nums < 1){
System.out.println("nums的值不正确");
return;
}
Boy curBoy = null; // 辅助指针,用来构建环形链表
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; // 把指针变成当前的boy
}
}
}
// 遍历当前环形链表
public void showBoy(){
if (first == null){
System.out.println("当前链表没有任何小孩");
return;
}
// 辅助指针
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("参数输入有误,请重新输入");
return;
}
// 创建要给辅助指针,帮助完成小孩出圈
Boy helper = first;
// 需求创建一个辅助指针(变量)helper,事先应该指向环形链表的最后这个节点
while (true){
if(helper.getNext() == first){
// 说明helper指向最后小孩节点
break;
}
helper = helper.getNext();
}
// 小孩报数前,先让first和helper移动k-1次
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 指针同时的移动 countNum - 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 = first.getNext();
helper.setNext(first);
}
System.out.printf("最后留在圈中的小孩编号%d \n", helper.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;
}
}