环形链表
实例:使用环形链表解决约瑟夫问题(丢手绢)
构建一个单向环形链表思路
1)先创建第一个节点,让first指向该节点,并形成环形
2)加入环形链表
遍历环形链表
1)先让一个辅助指针,指向first节点
2)while循环遍历环形链表
package com.cwnu.linkList.link;
import com.cwnu.linkList.node.Node;
//创建环形的单向链表
public class Josepfu {
//创建一个first节点,无编号节点
private Node first = null;
private int Number;
//添加小孩节点,构建环形链表
public void addBoy(int number) {//添加多少个节点
this.Number = number;
//number做一个数据校验
if (number < 1) {
System.out.println("数据无效");
return;
}
//辅助变量,帮助其构建环形链表
Node temp = null;
//for循环添加环形链表
for (int i = 1; i <= number; i++) {
//根据变量添加节点
Node boy = new Node(i);
if (i == 1) {
first = boy;
first.setNext(first);
temp = first;//辅助指针指向first
} else {
temp.next = boy;
boy.next = first;
temp = temp.next;
}
}
}
//遍历环形链表
public void showBoy() {
//判断链表是否为空
if (first == null) {
System.out.println("链表为空");
return;
}
Node temp = first;
while (true) {
System.out.printf("小孩的编号%d \n", temp.getNo());
if (temp.getNext() == first) {
//说明遍历完毕
break;
}
temp = temp.next;
}
}
//根据用户的输入,计算出小孩出圈顺序
/**
* @param startNo 表示开始报数小孩的number
* @param countNum 报多少次数
*/
public void countBoy(int startNo, int countNum) {
if (first == null || startNo < 1 || startNo > Number) {
System.out.println("参数输入有误");
return;
}
//创建辅助指针,帮助出圈,让其指向循环链表的最后节点
Node temp = first;
while (true) {
if (temp.getNext() == first) {
break;
}
temp = temp.next;
}
//初始化first节点和temp节点,将其指向用户输入的开始节点和开始前一个节点
for (int i = 0; i < startNo - 1; i++) {
first = first.next;
temp = temp.next;
}
while (true) {
if (first.next == temp.next){
//最后一个同学
System.out.printf("出列编号为%d", first.getNo());
break;
}
for (int i = 0; i < countNum - 1; i++) {
first = first.next;
temp = temp.next;
}
//此时first辅助节点指向的就是出列节点
temp.next = first.next;
System.out.printf("出列编号为%d\t", first.getNo());
first = first.next;
}
}
}