package element.io.data.structure.d4;
/**
* @author 张晓华
* @date 2022-12-18
* 单向循环链表
*/
public class SignleCircleLinkedList {
private Node first;
/**
* @param start 从第几个节点开始报数
* @param offset 报到几出圈
*/
public void count(int start, int offset) {
int size = size();
if (first == null || start > size || offset > size) {
return;
}
// 因为出圈操作first会移动,如果first移动了,但是之前节点的next没有移动,
// 就会导致循环链表断开,所以需要先找到最后一个节点
Node last = first;
while (last != null) {
if (last.next == first) {
break;
}
last = last.next;
}
// 将头节点移动到指定的位置
for (int i = 1; i < (start - 1); i++) {
first = first.next;
}
while (true) {
// 此处需要注意循环变量的控制
for (int i = 1; i <= (offset - 1); i++) {
// 直接将first移动到下一个目标元素的位置
first = first.next;
// 将最后一个节点的next指向到当前first的指向位置
last = last.next;
}
System.out.println(first.data);
// first继续移动到下一个元素的位置
first = first.next;
// 这个是关键,最后一个节点的next始终跟在头节点后面,
// 这样报数为offset的节点与其相邻节点的关秀就断开了
last.next = first;
if (last == first) {
System.out.println(last.data);
break;
}
}
}
/**
* @return 链表中元素的个数
*/
public int size() {
int count = 0;
if (first != null) {
Node temp = first;
while (temp != null) {
count++;
if (temp.next == first) {
break;
}
temp = temp.next;
}
}
return count;
}
public void list() {
if (first != null) {
Node temp = first;
while (temp != null) {
// 如果当前遍历到的节点的下一个节点就是first时就需要终止了,否则就会无限循环下去
if (temp.next == first) {
System.out.println(temp.data);
break;
}
System.out.println(temp.data);
temp = temp.next;
}
}
}
/**
* 添加指定数量的元素,在这个过程中必须保证first始终指向的是第一个元素
*
* @param num 要添加的元素的数量
*/
public void add(int num) {
if (num < 1) {
return;
}
Node temp = null;
for (int i = 1; i <= num; i++) {
if (i == 1) {
Node node = new Node(i);
// 此时first就指向了第一个节点
first = node;
// 第一个节点的next指向first,也就是指向自己,形成一个元素的循环链表
node.next = first;
// 记录下当前节点,因为需要保证first的指向不能发生变化
temp = first;
} else {
Node node = new Node(i);
// 让链表当前的最后一个节点的next指向新增的节点
temp.next = node;
// 新增的节点的next指向第一个元素
node.next = first;
// 指针后移
temp = node;
}
}
}
public class Node {
public int data;
public Node next;
public Node(int data) {
this.data = data;
}
}
}
10-03
234
08-09
606