单向环形列表---约瑟夫问题的解决方案

在这里插入图片描述

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;
		}
	}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值